Documentation
¶
Overview ¶
Package spec provides an LLM-facing tool for managing specification-driven work plans (create / status / validate / archive / …) without handing the agent a general shell.
Design intent: the plan agent must only ever touch the spec workspace. File reads/writes go through the sandboxed file tools (base_dir locked); spec management goes through this typed tool. There is deliberately NO exec in the plan agent's toolset — "only spec commands" is a structural fact, not a prompt-level hope.
The actual plan format is abstracted behind the Backend interface so the current openspec implementation can be swapped for another spec system without changing the tool surface the model sees.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewSpecTool ¶
NewSpecTool creates the spec-management function tool over a Backend. The tool surface is backend-agnostic; swapping the plan format only changes the Backend injected here.
func RegisterTool ¶
func RegisterTool()
RegisterTool registers the spec tool as a built-in plain tool ("spec"), backed by the openspec CLI. Agents opt in via config (kind: tool, id: spec). Properties:
- bin: openspec binary name/path (default "openspec")
- work_dir: working directory containing openspec/ (default: process cwd)
Types ¶
type Backend ¶
type Backend interface {
// Run executes one spec operation. Implementations must never run
// model-controlled strings through a shell; arguments are passed as
// discrete argv entries to a fixed program.
Run(ctx context.Context, req Request) (Result, error)
// Name identifies the backend (for logging / diagnostics).
Name() string
}
Backend abstracts a spec-management system. The current implementation is openspecBackend (shelling out to the openspec CLI); swapping the plan format means providing another Backend — the tool and the model never change.
func NewOpenSpecBackend ¶
func NewOpenSpecBackend(opts ...OpenSpecOption) Backend
NewOpenSpecBackend creates a Backend backed by the openspec CLI.
type Op ¶
type Op string
Op enumerates the spec-management operations exposed to the model. Keeping this a closed set (validated before dispatch) is what makes the tool safe: the model can only ever invoke a known operation, never an arbitrary command.
const ( OpInit Op = "init" // ensure the spec workspace exists (idempotent) OpNew Op = "new" // create a new change/plan by name OpStatus Op = "status" // query a change's artifact status OpValidate Op = "validate" // validate a change (strict) OpArchive Op = "archive" // archive a completed change OpInstructions Op = "instructions" // fetch the template for an artifact OpList Op = "list" // list existing changes )
type OpenSpecOption ¶
type OpenSpecOption func(*openspecBackend)
OpenSpecOption configures an openspec backend.
func WithOpenSpecBin ¶
func WithOpenSpecBin(bin string) OpenSpecOption
WithOpenSpecBin overrides the CLI binary name/path.
func WithWorkDir ¶
func WithWorkDir(dir string) OpenSpecOption
WithWorkDir sets the working directory for openspec invocations (the directory that contains openspec/). Defaults to the process cwd.
type Request ¶
type Request struct {
Op Op `json:"op"`
Name string `json:"name,omitempty"` // change/plan name (kebab-case)
Artifact string `json:"artifact,omitempty"` // for OpInstructions: proposal/specs/design/tasks
JSON bool `json:"json,omitempty"` // request machine-readable output where supported
}
Request is a single spec operation. Fields are optional per op; the Backend documents which it consumes.
type Result ¶
type Result struct {
Op Op `json:"op"`
ExitCode int `json:"exit_code"` // underlying process exit code (0 = success)
Output string `json:"output"` // combined stdout/stderr text
OK bool `json:"ok"` // convenience: ExitCode == 0
Hint string `json:"hint,omitempty"` // actionable guidance on failure
}
Result is the outcome of a spec operation.