lib

package module
v0.84.0 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2026 License: BSD-2-Clause Imports: 15 Imported by: 0

README

agent

Go Reference CI Go Report Card Ask DeepWiki

SDK + Claude Code plugin for the bborbe agent platform.

  • Go SDK — shared types, schemas, and runtime helpers consumed by every agent + task-system service in the ecosystem
  • Claude Code plugin/launch-agent slash command for interview-driven scaffolding of new agents

Quick start

Install the plugin (in Claude Code):

claude plugin marketplace add bborbe/agent
claude plugin install agent

Scaffold a new agent:

/launch-agent <name>

Walks you through the [[Agent Design Guide]] interview, recommends a reference shape (claude/code/gemini/pi), clones the matching template repo via gh repo create --template, customizes the clone, writes vault artifacts (knowledge page, goal, scenario, NEXT-DIRECTIONS), and prints a deploy checklist. See commands/launch-agent.md for the workflow.

What's in here

Single Go module at github.com/bborbe/agent with these subpackages:

Package Role
agent (root) Agent, Phase, Step, Status, Task, TaskFrontmatter, parser/markdown helpers — the runtime contract every agent honors
claude/ Claude Code runner helpers (used by agent-claude template)
pi/ MiniMax pi runner helpers (used by agent-pi template)
command/ CQRS command shapes (task.CreateCommand, task.UpdateFrontmatterCommand, task.IncrementFrontmatterCommand) + ErrTaskAlreadyExists sentinel
delivery/ ResultDeliverer interface (Kafka + file deliverers)
envparse/ Env-var parsing helpers for agent main.go bootstraps
healthcheck/ Generic agent liveness handler
metrics/ Prometheus metrics for agent + executor runtime
mocks/ counterfeiter-generated test doubles

Consumers

Each agent + task service lives in its own repo and imports this SDK:

Repo Role
agent-claude AI-heavy reference template (Claude Code) — is_template: true
agent-code Pure-Go reference template (deterministic phases)
agent-gemini Boundary-translator reference (Gemini at planning edge)
agent-pi Tier-D LLM reference (MiniMax Pi)
agent-task-controller Single git writer for the vault (Kafka → git via git-rest)
agent-task-executor Kafka event consumer + per-task K8s Job spawner

Producers (emit task commands)

Use as a Go module

go get github.com/bborbe/agent
import (
    "github.com/bborbe/agent"
    "github.com/bborbe/agent/delivery"
    "github.com/bborbe/agent/command/task"
)

History

This repo was a monorepo through 2026-06-24, hosting task/controller/, task/executor/, and 4 reference agents under agent/{claude,code,gemini,pi}/ as Go sub-modules + the SDK under lib/. On 2026-06-25 each service and reference agent was extracted to its own repo (see Consumers table above), the SDK was promoted from lib/ to the repo root, and the module identity collapsed from github.com/bborbe/agent/lib to github.com/bborbe/agent. See CHANGELOG.md ## v0.70.0 for the migration guide.

Older import path github.com/bborbe/agent/lib/... continues to resolve via historical tags (latest v0.69.0) for any consumer not yet migrated; new development happens at the flat path.

Plugin layout

.claude-plugin/, commands/, agents/, skills/, scenarios/ at repo root — same convention as bborbe/coding and bborbe/dark-factory.

Path Role
.claude-plugin/plugin.json + marketplace.json Plugin metadata
commands/launch-agent.md The /launch-agent slash command (thin dispatcher to the skill)
agents/agent-shape-picker.md Sonnet subagent: use case → shape recommendation with reasoning
skills/launch-agent/SKILL.md 8-phase orchestrator (interview → shape → clone → customize → render templates → commit → checklist)
skills/launch-agent/references/ shapes.md + interview.md + 4 output templates (config-crd, vault-page, goal, scenario) + next-directions
scenarios/001-launch-agent-happy-path.md End-to-end smoke test of the scaffolding flow

Architecture references

  • docs/kafka-schema-design.md — Kafka topic + command schema design
  • docs/task-flow-and-failure-semantics.md — task lifecycle + failure modes
  • docs/agent-job-interface.md — what every agent main.go must implement
  • docs/agent-job-lifecycle.md — phase + step lifecycle
  • docs/dod.md — definition of done
  • docs/deployment.md — platform deploy notes
  • Agent Hub — full architecture catalog (in personal vault)
  • Quick-Launch New Agents — the goal this split landed under

License

BSD-2-Clause.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var CDBSchemaIDs = cdb.SchemaIDs{
	TaskV1SchemaID,
}
View Source
var TaskV1SchemaID = cdb.SchemaID{
	Group:   "agent",
	Kind:    "task",
	Version: "v1",
}

Functions

func ExtractSection

func ExtractSection[T any](ctx context.Context, md *Markdown, heading string) (*T, error)

ExtractSection reads `heading` from the markdown, finds the first ```json fence inside its body, unmarshals into T, and returns a typed pointer.

Errors are formatted for use as needs_input messages:

  • "<heading> section missing" — heading not found
  • "<heading>: json block missing" — no ```json fence in section
  • "<heading>: json malformed: <detail>" — unmarshal failed

func ExtractSectionMap

func ExtractSectionMap(ctx context.Context, md *Markdown, heading string) (map[string]any, error)

ExtractSectionMap is the untyped variant — useful when the schema is not known statically.

func PrintResult

func PrintResult(ctx context.Context, result *Result) error

PrintResult marshals a framework Result to JSON and prints to stdout. nil result is a no-op (returns nil error). Used by agent main.go entry points to surface the terminal step outcome on stderr/stdout for log aggregators and the K8s Job exit observer.

Types

type AIParser

type AIParser interface {
	// Parse reads taskContent (markdown) and populates target (a pointer
	// to a typed struct).
	Parse(ctx context.Context, taskContent string, target any) error
}

AIParser is the boundary translator: fuzzy markdown → typed Go struct.

Concrete implementations wrap Gemini structured output, Claude with JSON mode, or any other LLM that produces structured outputs. They derive a JSON schema from the target type and instruct the LLM to emit conforming output.

Concrete impls live alongside their AI provider (e.g. lib/gemini for Gemini-backed parser). The interface lives here so framework code (ParseStep) can compose any provider without coupling.

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

Agent is a composed list of phases. Build via NewAgent.

func NewAgent

func NewAgent(phases ...Phase) *Agent

NewAgent constructs an Agent from one or more phases.

Phase names must be unique. Duplicates are rejected at Run time.

func (*Agent) Run

func (a *Agent) Run(
	ctx context.Context,
	phaseName domain.TaskPhase,
	taskContent string,
	deliverer ResultDeliverer,
) (*Result, error)

Run dispatches by phase and walks the matching step list.

phaseName is the requested phase from the K8s Job env (PHASE) or the CLI flag. Unknown or empty phaseName produces a Failed result via the deliverer (fail-loud sentinel — never a silent escalation).

taskContent is parsed once into *Markdown; the parsed Markdown is mutated by successive steps and re-serialized for each save.

On the happy path, Run walks phases sequentially in the same process: after a step publishes Done + NextPhase, if that NextPhase exists on this Agent, the loop runs it in-process instead of returning. The pod only exits on: result == nil, Status != Done, NextPhase == ""/"done"/ "human_review"/not-in-this-agent, or ctx cancellation.

Contract change: Done + NextPhase != "" no longer means "exit pod" — it means "the Agent decides whether to advance internally or hand off to the executor".

type AgentProvider

type AgentProvider interface {
	Get(ctx context.Context, taskType TaskType) (*Agent, error)
}

AgentProvider returns the *Agent registered for a given TaskType. Implementations are typically configured at boot via NewAgentProvider with a binary-specific dispatch table; the Get method is called once per task at the Kafka entry point.

func NewAgentProvider

func NewAgentProvider(name string, agents map[TaskType]*Agent) AgentProvider

NewAgentProvider wires a task_type → *Agent dispatch table. The name argument identifies the consuming binary in the error message returned on a map miss (e.g. "agent-claude") and should match the binary's serviceName constant.

The agents map is captured by reference; callers must not mutate it after construction. Pass a freshly-built map.

type AgentResultInfo

type AgentResultInfo struct {
	Status  AgentStatus
	Output  string // body content (typically heading + fenced JSON)
	Message string // human-readable status; used by failure/needs_input paths
	// NextPhase is the task phase the agent requests the controller to write
	// when Status == AgentStatusDone. Ignored on Failed/NeedsInput (failure
	// paths always escalate to human_review). Empty means "stay in current
	// phase" — an in-place save between steps of a multi-step phase; the
	// task keeps status: in_progress and its phase untouched. Terminating a
	// task requires an explicit NextPhase: "done". Valid values are vault-cli
	// TaskPhase enum strings: planning, execution, ai_review, human_review,
	// done ("in_progress" is a legacy alias for execution).
	NextPhase string
	// ContinueToNext mirrors Result.ContinueToNext: whether the StepRunner
	// proceeds to the next step in the same Job invocation. Informational
	// for deliverers — a Done result with empty NextPhase is an in-place
	// save regardless of this flag.
	ContinueToNext bool
}

AgentResultInfo holds the minimum fields a deliverer needs to publish a step's result. ResultDeliverer.DeliverResult takes this directly.

type AgentStatus

type AgentStatus string

AgentStatus represents the outcome status of a step (or single-shot agent).

const (
	// AgentStatusDone indicates the step completed successfully.
	// On the last step of a phase, set NextPhase to advance.
	// On a mid-phase step, leave NextPhase empty (in-place save).
	AgentStatusDone AgentStatus = "done"

	// AgentStatusInProgress indicates the step completed and saved partial state,
	// but the phase is not yet complete. Phase frontmatter is preserved.
	// Used by multi-step phases for in-place progress saves between steps.
	// NextPhase is ignored on this status.
	AgentStatusInProgress AgentStatus = "in_progress"

	// AgentStatusFailed indicates a transient infrastructure failure.
	// Controller retries (trigger_count++); after max_triggers, escalates.
	AgentStatusFailed AgentStatus = "failed"

	// AgentStatusNeedsInput indicates a semantic problem in the task body.
	// Routed straight to human_review — retrying won't help.
	AgentStatusNeedsInput AgentStatus = "needs_input"
)

type Markdown

type Markdown struct {
	Frontmatter TaskFrontmatter
	Preamble    string
	Sections    []Section
}

Markdown is a parsed task document: frontmatter + preamble (text before the first section) + ordered list of sections.

Steps mutate Markdown in place via the methods below. The framework re-serializes Markdown via Marshal after each step's Run and publishes the new content via the deliverer.

func ParseMarkdown

func ParseMarkdown(_ context.Context, content string) (*Markdown, error)

ParseMarkdown parses raw markdown into a Markdown document.

Best-effort parsing: invalid YAML returns an empty Frontmatter without error. Sections are split at every "# " or "## " heading; "### " and deeper sub-headings are part of the parent section's Body.

func (*Markdown) AddSection

func (m *Markdown) AddSection(section Section)

AddSection appends a section to the end of the section list.

Use ReplaceSection if a section with the same heading might already exist; AddSection does not deduplicate.

func (*Markdown) FindSection

func (m *Markdown) FindSection(heading string) (*Section, bool)

FindSection returns a pointer to the first section matching heading, and a bool indicating presence. Mutating the returned section's fields updates the Markdown in-place.

func (*Markdown) InsertSection

func (m *Markdown) InsertSection(pos int, section Section)

InsertSection inserts a section at the given position. Out-of-range positions clamp to [0, len(Sections)].

func (*Markdown) Marshal

func (m *Markdown) Marshal(ctx context.Context) (string, error)

Marshal serializes the Markdown back to a markdown string.

Output: "---\n<yaml>\n---\n<preamble><section><section>..." Each section is rendered as "<heading>\n\n<body>\n" if body is non-empty, or "<heading>\n" if body is empty.

func (*Markdown) ReplaceSection

func (m *Markdown) ReplaceSection(section Section)

ReplaceSection replaces the existing section with the same Heading, or appends if no match exists. Idempotent for "save my output" steps.

type ParseStep

type ParseStep[T any] struct {
	// contains filtered or unexported fields
}

ParseStep wraps an AIParser as a Step.

Boundary translator: markdown → typed Go struct → ## Section JSON. Use this for the planning phase of code-driven agents that take fuzzy human-written tasks.

func NewParseStep

func NewParseStep[T any](
	name string,
	parser AIParser,
	heading string,
	nextPhase string,
) *ParseStep[T]

NewParseStep constructs a ParseStep[T].

name: step name for logs (e.g. "parse-plan") parser: the AI parser implementation (Gemini structured output, etc.) heading: the body section to write the typed result to (e.g. "## Plan") nextPhase: the phase to advance to on success

func (*ParseStep[T]) Name

func (s *ParseStep[T]) Name() string

Name implements Step.

func (*ParseStep[T]) Run

func (s *ParseStep[T]) Run(ctx context.Context, md *Markdown) (*Result, error)

Run invokes the parser, marshals the typed result as a Section, returns Result.

func (*ParseStep[T]) ShouldRun

func (s *ParseStep[T]) ShouldRun(_ context.Context, md *Markdown) (bool, error)

ShouldRun returns false if the target section already exists.

type Phase

type Phase struct {
	Name  domain.TaskPhase
	Steps []Step
}

Phase ties a phase name to an ordered list of steps.

Compose with NewAgent:

NewAgent(
    NewPhase("planning",   NewParseStep(parser, "## Plan", "in_progress")),
    NewPhase("in_progress", NewExecuteStep(runner, fetcher)),
    NewPhase("ai_review",  NewVerifyStep(checker)),
)

func NewPhase

func NewPhase(name domain.TaskPhase, steps ...Step) Phase

NewPhase constructs a Phase. Variadic steps for ergonomics.

type Result

type Result struct {
	// Status: Done | InProgress | Failed | NeedsInput.
	Status AgentStatus

	// NextPhase advances the phase frontmatter on Status: Done. Empty
	// means "stay in current phase" — used for in-place saves between
	// steps in a multi-step phase.
	NextPhase string

	// Message is a human-readable status. Required for Failed/NeedsInput.
	Message string

	// ContinueToNext signals whether the StepRunner should proceed to
	// the next step in the same Job invocation (true) or exit and let
	// the controller re-trigger the same phase (false).
	//
	// Default is exit-after-save. Multi-step phases set this to true on
	// intermediate steps and let the last step decide.
	ContinueToNext bool
}

Result tells the StepRunner what status to deliver and whether to advance.

Body and frontmatter changes are NOT in Result — they're applied by mutating *Markdown in Run. This keeps the durability model clear: at any point during Run, the Markdown IS the durable view.

type ResultDeliverer

type ResultDeliverer interface {
	DeliverResult(ctx context.Context, result AgentResultInfo) error
}

ResultDeliverer publishes an agent step result back to the task controller.

Implementations live in lib/delivery: NoopResultDeliverer (tests), FileResultDeliverer (local CLI), KafkaResultDeliverer (production K8s).

type Section

type Section struct {
	Heading string
	Body    string
}

Section is one heading-bounded block in a parsed markdown document.

Heading is the exact heading line including '#' characters, e.g. "## Plan". Body is the content between this heading and the next at the same or higher level (no trailing newline).

Section is the parsed structural unit. The CQRS BodySection (in lib/command/task) is a different concept: it carries the full serialized section text including the heading line, used as a partial frontmatter+body update payload.

func MarshalSectionTyped

func MarshalSectionTyped[T any](ctx context.Context, heading string, value T) (Section, error)

MarshalSectionTyped renders a typed value as a Section ready for markdown.AddSection or markdown.ReplaceSection.

Output Section.Body format:

```json
{
  "field": "value"
}
```

Round-trips with ExtractSection for the same heading and type.

type Step

type Step interface {
	// Name identifies the step. Convention: lower-kebab-case.
	Name() string

	// ShouldRun returns true if the step should execute. Inspects markdown
	// state (frontmatter, sections) and returns false if the step has
	// already completed (idempotency guard).
	//
	// Guards must be cheap — no expensive I/O. Use existing markdown state.
	ShouldRun(ctx context.Context, md *Markdown) (bool, error)

	// Run performs the step's work, mutating markdown in-place. Returns a
	// Result describing status + phase transition. Body content changes
	// flow through markdown.AddSection / ReplaceSection; frontmatter
	// changes flow through direct map mutation.
	//
	// The framework re-serializes markdown via Marshal after Run returns
	// and publishes the new content via the deliverer.
	Run(ctx context.Context, md *Markdown) (*Result, error)
}

Step is one unit of work within a phase. Always code; may wrap AI calls.

Three responsibilities:

  • Name: identifies the step in logs and tests.
  • ShouldRun: cheap guard that inspects task state to decide skip vs run.
  • Run: performs work, mutating markdown in-place. Returns a Result describing status + phase transition (NOT body content — body changes happen via markdown.AddSection / ReplaceSection / Frontmatter mutation).

type StepRunner

type StepRunner struct {
	// contains filtered or unexported fields
}

StepRunner walks an ordered list of steps for a single phase invocation.

On each iteration:

  1. step.ShouldRun(markdown) — skip if false
  2. step.Run(markdown) — mutates markdown in-place, returns Result
  3. markdown.Marshal() → newContent
  4. deliverer.DeliverResult(newContent, status, nextPhase)
  5. Decides whether to continue based on Status, NextPhase, ContinueToNext

Resume semantics: the runner does NOT track "current step" state. On re-invocation, all steps are re-walked; their ShouldRun guards skip completed work based on saved markdown state. Markdown state IS the resume cursor.

func NewStepRunner

func NewStepRunner(deliverer ResultDeliverer, steps ...Step) *StepRunner

NewStepRunner constructs a StepRunner with the given step list and deliverer.

func (*StepRunner) Run

func (r *StepRunner) Run(ctx context.Context, md *Markdown) (*Result, error)

Run walks the step list, calling guards, running, marshaling, and saving. Returns the last delivered Result, or nil if no step executed.

type Task

type Task struct {
	base.Object[base.Identifier]
	TaskIdentifier TaskIdentifier  `json:"taskIdentifier"`
	Frontmatter    TaskFrontmatter `json:"frontmatter"`
	Content        TaskContent     `json:"content"`
}

Task is the payload published by an agent when it finishes a task. task/controller consumes this from agent-task-v1-request and writes it to the vault file. Frontmatter is a generic map — task/controller serializes it to YAML without interpreting individual fields. Content is the markdown body after the frontmatter closing delimiter. The agent owns the content transformation (status, phase, Result section, etc.).

func (Task) Ptr

func (t Task) Ptr() *Task

func (Task) Validate

func (t Task) Validate(ctx context.Context) error

type TaskAssignee

type TaskAssignee string

TaskAssignee identifies which agent type handles this task. Matched against Config CRD spec.assignee.

func (TaskAssignee) String

func (t TaskAssignee) String() string

func (TaskAssignee) Validate

func (t TaskAssignee) Validate(ctx context.Context) error

type TaskContent

type TaskContent string

TaskContent is the markdown body of a task after the frontmatter closing delimiter.

func (TaskContent) String

func (t TaskContent) String() string

func (TaskContent) Validate

func (t TaskContent) Validate(ctx context.Context) error

type TaskFrontmatter

type TaskFrontmatter map[string]interface{}

TaskFrontmatter is a generic map of frontmatter key-value pairs. Serializable as JSON (Kafka) and YAML (vault file). Typed accessors provide type-safe access to well-known fields.

func (TaskFrontmatter) Assignee

func (f TaskFrontmatter) Assignee() TaskAssignee

func (TaskFrontmatter) CurrentJob

func (f TaskFrontmatter) CurrentJob() string

CurrentJob returns the K8s Job name recorded when the executor spawned a Job for this task. Returns an empty string when not set.

func (TaskFrontmatter) Int

func (f TaskFrontmatter) Int(key string) (int, bool)

Int reads an integer field by key, accepting both int (JSON-decoded) and float64 (YAML-decoded) underlying types. ok is false when the key is absent or holds a non-numeric value. Generic accessor for ad-hoc fields without dedicated typed methods.

func (TaskFrontmatter) JobStartedAt

func (f TaskFrontmatter) JobStartedAt() (time.Time, error)

JobStartedAt parses the job_started_at frontmatter field written by PublishSpawnNotification. Returns (time.Time{}, nil) when the field is absent — callers treat zero time as "grace elapsed". Returns (time.Time{}, err) when the field is present but unparseable.

func (TaskFrontmatter) MaxRetries

func (f TaskFrontmatter) MaxRetries() int

MaxRetries returns the maximum number of failures allowed before escalation. Returns 3 when the field is absent (spec default).

func (TaskFrontmatter) MaxTriggers

func (f TaskFrontmatter) MaxTriggers() int

MaxTriggers returns the maximum number of spawn-trigger events allowed for this task. Returns 3 if the field is absent, matching the default for max_retries.

func (TaskFrontmatter) Phase

func (f TaskFrontmatter) Phase() *domain.TaskPhase

func (TaskFrontmatter) RetryCount

func (f TaskFrontmatter) RetryCount() int

RetryCount returns the number of failed attempts recorded in frontmatter. Returns 0 when the field is absent.

func (TaskFrontmatter) SpawnNotification

func (f TaskFrontmatter) SpawnNotification() bool

SpawnNotification returns true when this result is a job-spawn tracking update rather than an agent outcome. The controller skips the retry counter for these.

func (TaskFrontmatter) Stage

func (f TaskFrontmatter) Stage() string

Stage returns the execution stage from the "stage" key. Returns "prod" if the key is absent or empty.

func (TaskFrontmatter) Status

func (f TaskFrontmatter) Status() domain.TaskStatus

func (TaskFrontmatter) String

func (f TaskFrontmatter) String(key string) (string, bool)

String reads a string field by key. ok is false when the key is absent or holds a non-string value. Generic accessor for ad-hoc fields without dedicated typed methods.

func (TaskFrontmatter) TaskType

func (f TaskFrontmatter) TaskType() TaskType

TaskType returns the task_type frontmatter field as a typed TaskType. Returns TaskType("") when the field is absent or holds a non-string value.

func (TaskFrontmatter) TriggerCount

func (f TaskFrontmatter) TriggerCount() int

TriggerCount returns the number of spawn-trigger events that have fired for this task. Returns 0 if the field is absent.

type TaskIdentifier

type TaskIdentifier string

TaskIdentifier uniquely identifies an agent task.

func (TaskIdentifier) Bytes

func (t TaskIdentifier) Bytes() []byte

func (TaskIdentifier) Equal

func (t TaskIdentifier) Equal(identifier base.ObjectIdentifier) bool

func (TaskIdentifier) Ptr

func (t TaskIdentifier) Ptr() *TaskIdentifier

func (TaskIdentifier) String

func (t TaskIdentifier) String() string

func (TaskIdentifier) Validate

func (t TaskIdentifier) Validate(ctx context.Context) error

type TaskIdentifierGenerator

type TaskIdentifierGenerator base.IdentifierGenerator[TaskIdentifier]

TaskIdentifierGenerator generates unique task identifiers.

type TaskIdentifiers

type TaskIdentifiers []TaskIdentifier

TaskIdentifiers is a slice of TaskIdentifier.

func (TaskIdentifiers) Contains

func (t TaskIdentifiers) Contains(value TaskIdentifier) bool

Contains returns true if the slice contains the given identifier.

type TaskType

type TaskType string

TaskType identifies the category of work a task represents. Matched against the agent's declared task-type set before spawning a Job.

const (
	// TaskTypeLLM is the task type for generic LLM agent jobs.
	TaskTypeLLM TaskType = "llm"
	// TaskTypePRReview is the task type for PR review jobs.
	TaskTypePRReview TaskType = "pr-review"
	// TaskTypeBacktest is the task type for backtesting jobs.
	TaskTypeBacktest TaskType = "backtest"
	// TaskTypeHypothesis is the task type for hypothesis evaluation jobs.
	TaskTypeHypothesis TaskType = "hypothesis"
	// TaskTypeTradeAnalysis is the task type for trade analysis jobs.
	TaskTypeTradeAnalysis TaskType = "trade-analysis"
	// TaskTypeOAuthProbe is the task type for OAuth probe health-check jobs.
	//
	// Deprecated: use TaskTypeHealthcheck.
	TaskTypeOAuthProbe TaskType = "oauth-probe"
	// TaskTypeHealthcheck is the liveness task type for all agent binaries.
	// Dispatches to the binary's corresponding healthcheck step in lib/healthcheck.
	TaskTypeHealthcheck TaskType = "healthcheck"
)

func (TaskType) Bytes

func (t TaskType) Bytes() []byte

func (TaskType) Ptr

func (t TaskType) Ptr() *TaskType

func (TaskType) String

func (t TaskType) String() string

func (TaskType) Validate

func (t TaskType) Validate(ctx context.Context) error

Validate returns an error when the task type is empty, contains characters outside [a-z0-9-], or exceeds 63 characters — matching the CRD-side constraint.

Directories

Path Synopsis
agent
claude module
command
Package envparse provides simple parsers for KEY=VALUE-style CLI inputs.
Package envparse provides simple parsers for KEY=VALUE-style CLI inputs.
lib module
mocks
Code generated by counterfeiter.
Code generated by counterfeiter.
Code generated by counterfeiter.
Code generated by counterfeiter.

Jump to

Keyboard shortcuts

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