skills

package
v0.0.32 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package skills is the in-repo adapter for Agent Skills. The READ-ONLY core (discovery, source, and Skill tool) graduated into the importable engine module (engine/adapter/skillfs, issue #328) and is re-exported here via thin type/func/const aliases; the writable SkillDraft half stays in this package and reaches the core through those aliases. See alias.go and the skillfs package doc for the real contract.

Index

Constants

View Source
const (
	MaxLicenseBytes         = skillfs.MaxLicenseBytes
	MaxCompatibilityBytes   = skillfs.MaxCompatibilityBytes
	MaxMetadataEntries      = skillfs.MaxMetadataEntries
	MaxMetadataValueBytes   = skillfs.MaxMetadataValueBytes
	MaxAllowedTools         = skillfs.MaxAllowedTools
	MaxAllowedToolNameBytes = skillfs.MaxAllowedToolNameBytes
)

MaxLicenseBytes, MaxCompatibilityBytes, MaxMetadataEntries, and MaxMetadataValueBytes are the advisory caps for the optional license/ compatibility/metadata frontmatter. See the skillfs constants. Exported so the remote-driver client (grpcdriver) re-clamps defensively to the SAME caps the parser uses.

MaxAllowedTools and MaxAllowedToolNameBytes are the advisory caps for the optional `allowed-tools` frontmatter (agentskills.io, Experimental). Same export rationale.

View Source
const DefaultDir = skillfs.DefaultDir

DefaultDir is the conventional project-level skills directory. See skillfs.DefaultDir.

View Source
const DefaultSimilarityThreshold = 0.5

DefaultSimilarityThreshold is the default 2-gram Jaccard similarity above which a candidate's description is flagged as a near-duplicate of an existing skill. It WARNS (returned in DraftResult.SimilarSkills); it never blocks — the model decides whether to refine or proceed.

View Source
const DraftToolName = "SkillDraft"

DraftToolName is the catalog name of the writable skill-authoring tool.

View Source
const MaxDescriptionBytes = skillfs.MaxDescriptionBytes

MaxDescriptionBytes caps a skill's one-line description. See skillfs.MaxDescriptionBytes.

View Source
const ProjectDirClaude = skillfs.ProjectDirClaude

ProjectDirClaude is the Claude-Code-compatible project-level skills dir. See skillfs.ProjectDirClaude.

View Source
const ProjectDirMecatl = skillfs.ProjectDirMecatl

ProjectDirMecatl is the project-level skills dir under the workspace. See skillfs.ProjectDirMecatl.

View Source
const QuarantineSubdir = "skills-quarantine"

QuarantineSubdir is the conventional name of the quarantine directory the DirDrafter writes candidate skills into when the composition root derives the quarantine location from a base directory. The quarantine dir is NEVER served to the live catalog (see the trust boundary in doc.go); it is only read by the novelty check and the promote CLI.

View Source
const SkillFileName = skillfs.SkillFileName

SkillFileName is the conventional file every skill directory contains. See skillfs.SkillFileName.

View Source
const ToolName = skillfs.ToolName

ToolName is the catalog name of the single skills tool. See skillfs.ToolName.

Variables

This section is empty.

Functions

func Discover

func Discover(dir string) ([]Skill, []SkipError, error)

Discover scans dir for skills. See skillfs.Discover.

func ImportLegacyDraft

func ImportLegacyDraft(ctx context.Context, repo learning.SkillRepository, partition learning.SkillPartition, owner, quarantineDir, name string, inventory []learning.SkillInventoryItem) (learning.SkillVersion, error)

ImportLegacyDraft explicitly imports one origin:model quarantine candidate into the evaluated lifecycle as an unevidenced agent-owned Draft. It rejects assets, scripts, and inventory collisions; it never stages or activates the result.

func Jaccard2Gram

func Jaccard2Gram(a, b string) float64

Jaccard2Gram returns the 2-gram (character-bigram) Jaccard similarity between a and b, in [0,1]: |A∩B| / |A∪B| over the SET of adjacent character pairs of each (case-folded, whitespace-collapsed). It is an offline, dependency-free, near-oracle novelty signal — no embeddings, no network — used to flag a candidate skill's description as a near-duplicate of an existing one.

Identical strings score 1.0; strings with no shared bigram score 0.0. Two strings shorter than one bigram each (e.g. both empty) score 1.0 when equal, 0.0 otherwise.

func NewDraftTool

func NewDraftTool(d Drafter) tool.Tool

NewDraftTool constructs the SkillDraft tool bound to d. d must be non-nil; the composition root registers this tool only when a quarantine dir is configured.

func NewFSSource

func NewFSSource(ctx context.Context, sources ...Source) (*FSSource, []SkipError, error)

NewFSSource resolves the given sources ONCE and returns the snapshot source plus the aggregated discovery diagnostics. See skillfs.NewFSSource.

func NewSkillCommandSource

func NewSkillCommandSource(metas []tool.SkillMeta, source tool.SkillSource) prompt.CommandSource

NewSkillCommandSource builds a prompt.CommandSource over the resolved logical source so each discovered skill is invocable as /<skill-name>.

func Promote

func Promote(quarantineDir, activeDir, name string) error

Promote moves a quarantined candidate skill <quarantineDir>/<name>/ into the operator's active <activeDir>/<name>/, re-running structural validation as defense in depth.

This is the legacy operator/manual filesystem workflow. It does not read or activate lifecycle repository records. New integrations should use ImportLegacyDraft and evaluate/stage/activate through SkillRepository.

It is the OPERATOR gate: the only path from model-authored quarantine to the live, trusted skill catalog. It requires filesystem access the model does not have, and is invoked by the `mecated skills promote` subcommand, never by a tool.

It fails (and moves nothing) when:

  • name is not a valid activation name,
  • the candidate is missing or unreadable,
  • the candidate lacks `origin: model` provenance (only model-drafted candidates may be promoted),
  • the candidate fails structural validation (parseSkill) or the injection scan (so an attacker who somehow planted a quarantine file cannot promote instruction-laden content),
  • a skill with that name already exists under activeDir (no silent overwrite).

Promote performs no human review itself: the `mecated skills promote` CLI shows the operator the full candidate (ReadCandidate) and requires confirmation before calling this. The injection scan here is a backstop, not a substitute for a human reading the body. The move is a directory rename, so the provenance frontmatter (origin: model, drafted_at) is carried over for the audit trail.

func ReadCandidate

func ReadCandidate(quarantineDir, name string) ([]byte, error)

ReadCandidate returns the raw SKILL.md bytes of a quarantined candidate, for the operator to review before promoting. It validates the name (so a traversal name cannot read outside the quarantine) and returns a clear error when the candidate is absent.

func Register

func Register(cat *tool.Catalog, dir string) ([]Skill, []SkipError, error)

Register discovers skills under a single directory and registers the Skill tool. See skillfs.Register.

func RegisterSource

func RegisterSource(ctx context.Context, cat *tool.Catalog, src Source) ([]Skill, []SkipError, error)

RegisterSource discovers skills from src and, when at least one valid skill is found, registers a single Skill tool into cat. See skillfs.RegisterSource.

func ScanForInjection

func ScanForInjection(s string) (marker string, found bool)

ScanForInjection scans s for any disallowed instruction-injection / role- override marker. See skillfs.ScanForInjection.

func ValidSkillName

func ValidSkillName(name string) bool

ValidSkillName reports whether name is a valid skill activation name under the shared grammar. It is exported so this package's writable half (the DirDrafter's validateName) routes through the SAME validator the read-only discovery core uses — a single source of truth, not two regexes to drift. See skillfs.ValidSkillName.

Types

type DirDrafter

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

DirDrafter is the local-filesystem Drafter. It writes candidates as <QuarantineDir>/<name>/SKILL.md with a provenance-stamped frontmatter, reusing parseSkill/validateName for validation and a snapshot of the active skill descriptions (taken at construction) for the offline novelty check.

func NewDirDrafter

func NewDirDrafter(quarantineDir string, existing []Skill, opts ...DraftOption) *DirDrafter

NewDirDrafter builds a DirDrafter that writes quarantined candidates under quarantineDir and runs the novelty check against existing (a snapshot of the currently active skills). quarantineDir must be a directory the model has NO other write path into (the composition root enforces this with a governance deny rule on Write/Edit and asserts the dir is disjoint from every active skills dir).

func (*DirDrafter) Draft

func (d *DirDrafter) Draft(ctx context.Context, req DraftRequest) (DraftResult, error)

Draft validates, sanitizes, novelty-checks, and atomically writes the candidate. On any validation/sanitization failure it returns ("", err) with NO file written. The novelty check never blocks: a near-duplicate is reported in DraftResult.SimilarSkills/Warnings and the candidate is still written.

type DirSource

type DirSource = skillfs.DirSource

DirSource is the local-OS-filesystem implementation of Source. See skillfs.DirSource.

type DraftOption

type DraftOption func(*DirDrafter)

DraftOption configures a DirDrafter.

func WithClock

func WithClock(now func() time.Time) DraftOption

WithClock injects a deterministic time source for the `drafted_at` provenance stamp (tests pass a fixed clock). The default is time.Now.

func WithNeutralValidation

func WithNeutralValidation(enabled bool) DraftOption

WithNeutralValidation controls the shared logical skill validator. Validation is enabled by default; false is the explicit compatibility escape hatch for a host that has not yet migrated its legacy quarantine policy.

func WithSimilarityThreshold

func WithSimilarityThreshold(t float64) DraftOption

WithSimilarityThreshold overrides the 2-gram Jaccard threshold above which the novelty check flags a near-duplicate description. Values outside (0,1] are ignored (the default stands).

type DraftRequest

type DraftRequest struct {
	// Name is the proposed activation name (frontmatter `name`).
	Name string
	// Description is the one-line, always-in-context metadata (frontmatter
	// `description`). It is scanned for injection markers because, if the skill
	// were ever promoted, it would join the always-in-context layer.
	Description string
	// Body is the markdown instructions (loaded on activation).
	Body string
}

DraftRequest is one candidate skill the model proposes. It is UNTRUSTED model output: every field is sanitized and validated by the Drafter before any byte touches disk.

type DraftResult

type DraftResult struct {
	// Path is where the candidate was written (under the quarantine dir), or ""
	// when nothing was written (a validation/sanitization failure).
	Path string
	// SimilarSkills lists existing skill names whose description is a near-duplicate
	// of the candidate's (at/above the similarity threshold). It is a warning, not
	// a block.
	SimilarSkills []string
	// Warnings holds non-fatal notes (e.g. description truncation, similarity over
	// the threshold) the tool surfaces to the model.
	Warnings []string
}

DraftResult reports the outcome of a draft attempt for the model to read back.

type DraftTool

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

DraftTool is the writable skill-authoring tool. It is MUTATING (ReadOnly() == false): it writes a candidate SKILL.md to the quarantine via the injected Drafter. Because it is mutating, the dispatcher runs it alone/serially and the catalog filters it out of plan mode. The Drafter is constructor- injected, the write-side mirror of how the read-only Skill tool takes a Source.

func (DraftTool) Execute

Execute validates and quarantines the candidate skill. A validation/ sanitization failure is returned as a model-addressable error result (never a harness-level Go error), so the model can revise and retry. On success the result names the quarantine path and any near-duplicate warnings.

func (DraftTool) ReadOnly

func (DraftTool) ReadOnly() bool

ReadOnly reports that SkillDraft mutates persistent state (it writes a file).

func (DraftTool) Spec

func (DraftTool) Spec() tool.ToolSpec

Spec returns the model-facing specification.

type Drafter

type Drafter interface {
	// Draft validates req, runs the novelty check, and on success writes the
	// candidate SKILL.md under the quarantine dir. A validation/sanitization
	// failure returns a non-nil error whose message is model-addressable (the
	// SkillDraft tool turns it into a NewToolError, never a harness fault) and
	// DraftResult.Path is "" (no file written).
	Draft(ctx context.Context, req DraftRequest) (DraftResult, error)
}

Drafter is the WRITE seam: it accepts an untrusted candidate skill, validates and sanitizes it, checks it for novelty against the existing skills, and on success persists it to a QUARANTINE location that is NOT part of any catalog- registered Source. It NEVER writes into a directory that DirSource serves to a live Skill tool. Construction binds it to (a) the quarantine dir and (b) a read-only snapshot of the currently active skills for the novelty check.

LAYERING: this is an adapter-package seam, the write-side mirror of Source (also an adapter-package seam, not a domain port). The domain never imports it; the SkillDraft tool depends on it by constructor injection, the same shape by which the read-only Skill tool depends on Source.

type FSSource

type FSSource = skillfs.FSSource

FSSource is the FILESYSTEM implementation of the tool.SkillSource port. See skillfs.FSSource.

type LifecycleDrafter

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

LifecycleDrafter persists explicit model drafts as versioned, inactive agent-owned records. It never writes to or publishes the live catalog.

func NewLifecycleDrafter

func NewLifecycleDrafter(repository learning.SkillRepository, partition learning.SkillPartition, owner string, inventory []learning.SkillInventoryItem) *LifecycleDrafter

NewLifecycleDrafter binds explicit model drafts to an inactive lifecycle partition.

func (*LifecycleDrafter) Draft

func (d *LifecycleDrafter) Draft(ctx context.Context, request DraftRequest) (DraftResult, error)

Draft validates and persists one inactive versioned draft.

func (*LifecycleDrafter) DraftIn

func (d *LifecycleDrafter) DraftIn(ctx context.Context, env tool.Environment, request DraftRequest) (DraftResult, error)

DraftIn derives model-facing draft ownership from the verified caller and exact live workspace. Missing identity or workspace disables drafting rather than writing to a process-global ownerless partition.

type MultiSource

type MultiSource = skillfs.MultiSource

MultiSource composes an ORDERED list of Sources into one. See skillfs.MultiSource.

type ResolveOptions

type ResolveOptions = skillfs.ResolveOptions

ResolveOptions configures the known-path resolver. See skillfs.ResolveOptions.

type Skill

type Skill = skillfs.Skill

Skill is a pure value object: one discovered skill's metadata and body. See skillfs.Skill.

func ParseSkill

func ParseSkill(raw []byte, path string) (Skill, string, []string)

ParseSkill splits raw into YAML frontmatter and a markdown body and validates the required header fields. It is exported so this package's writable half (promote.go) re-runs the promotion-gate structural validation through the SAME parser the read-only core uses. See skillfs.ParseSkill.

type SkipError

type SkipError = skillfs.SkipError

SkipError records one diagnostic from discovery. See skillfs.SkipError.

type Source

type Source = skillfs.Source

Source is the pluggable EXTENSIBILITY POINT for where skills come from. See skillfs.Source.

func ResolveSources

func ResolveSources(opts ResolveOptions) []Source

ResolveSources builds the ORDERED, highest-precedence-first Source list from the conventional locations plus any explicit paths. See skillfs.ResolveSources.

type Tool

type Tool = skillfs.Tool

Tool is the single model-facing skills tool. See skillfs.Tool.

func NewTool

func NewTool(metas []tool.SkillMeta, source tool.SkillSource) Tool

NewTool builds the Skill tool over the given skill metadata and logical source. See skillfs.NewTool.

Jump to

Keyboard shortcuts

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