Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .agents/skills/go-engineer/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,11 @@ first function that exposes the symptom.
`fragmentation` -> write or compare.
- **Keep functions small and explicit.** Prefer direct code over broad helpers
unless an abstraction removes real duplication or clarifies a shared contract.
- **Document every function and method.** Add concise doc comments to new or
changed functions, including unexported ones. Exported comments start with
the declaration name.
- **Document functions, methods, and struct fields.** Add concise doc comments
to new or changed functions, including unexported ones. Document every field
of a named struct directly above its declaration, including unexported fields;
keep the struct comment focused on the type as a whole. Exported comments
start with the declaration name.
- **Return actionable errors.** Add file, pattern, instruction, or operation
context where that context becomes known.
- **Aggregate independent failures with `errors.Join`.** Continue processing
Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/go-tester/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description: >
helper code.
---

# Go tester
# Go Testing

This skill is the single source of truth for how tests are written in
`embed-code-go`. It does not decide what behavior to change; it decides how to
Expand Down
6 changes: 5 additions & 1 deletion .agents/skills/review-docs/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description: >
builds unless explicitly asked.
---

# Review documentation (repo-specific)
# Documentation Review

You are the documentation reviewer for `embed-code-go`. Focus strictly on
documentation quality: Go doc comments, inline comments, Markdown, examples,
Expand Down Expand Up @@ -38,6 +38,10 @@ and repository guidance. Do not duplicate `writer` for authoring strategy,
Go doc style for exported types, constants, variables, functions, and methods.
- **Unexported comments explain intent.** Starting with the function name is
preferred when it reads naturally.
- **Every named struct field is documented in place.** Require a comment
directly above each exported or unexported field, starting with the exact
field name. Keep the struct comment focused on the type and reject field
descriptions collected there or duplicated at struct literals.
- **Comments describe behavior, not signatures.** Avoid prose that only
restates parameters, return values, or obvious assignments.
- **Mention important effects.** Document filesystem writes, state transitions,
Expand Down
40 changes: 39 additions & 1 deletion .agents/skills/writer/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: >
current Go code, tests, fixtures, and project flows.
---

# Write documentation
# Documentation Writing

## Decide the Target and Audience

Expand Down Expand Up @@ -74,12 +74,50 @@ Prefer updating an existing document over creating a new one.
- Exported comments start with the exact declaration name.
- Unexported comments state intent and start with the function name when it
reads naturally.
- Document named types, interfaces, exported constants, exported variables,
functions, methods, and struct fields. For unexported declarations, preserve
existing documentation and add comments when the declaration is new, changed,
non-obvious, or part of a local contract.
- Document every field of a named struct directly above the field declaration,
including unexported fields. Start with the exact field name and use normal
Go prose such as `FieldName is...` or `fieldName contains...`.
- Keep struct comments focused on the type as a whole. Do not collect field
descriptions in the struct comment or duplicate them at struct literals.
- Document non-obvious state transitions, filesystem writes, returned errors,
panics, and parser constraints.
- Preserve existing parameter, return, and author/explanatory comments. When
restyling, convert the content to project style instead of deleting it, even
for private functions.
- Do not restate the signature or narrate obvious assignments.
- Inline comments in production Go should explain why a constraint exists, not
what the next line does.

## Go Function Comment Style

Use this structure for functions and methods when parameters or returns need
documentation:

```go
// EmbedAll embeds code fragments into all documentation files selected by config.
//
// Parameters:
// config - provides embedding configuration.
//
// Returns:
// EmbedAllResult - embedding result.
// error - when selected documents fail to process.
```

- Keep the opening sentence short and behavioral.
- Use `Parameters:` when documenting parameters. Each line is
`<name> - <short meaningful description>`.
- Use `Returns:` only when there are multiple return values. Each line is
`<type> - <short meaningful description>`.
- For a single return value, use one sentence such as
`Returns parsed configuration.`
- Keep existing examples, constraints, and behavior notes, but normalize bullets
and parameter descriptions to this style.

## Make Docs Actionable

- Prefer executable steps, expected outcomes, and concrete examples over broad descriptions.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ failures, and runnable examples.

## Run

Download the asset for your platform from [GitHub Releases][releases].
Download the asset for your platform from [GitHub Releases][releases].

On Linux, for example:

Expand Down
150 changes: 91 additions & 59 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,79 +33,97 @@ import (
"gopkg.in/yaml.v3"
)

// Config — user-specified embed-code configurations.
//
// BaseCodePaths — a NamedPathList to directories with code files.
//
// BaseDocsPath — a path to a root directory with docs files.
//
// DocIncludes — a StringList with patterns for filtering files
// in which we should look for embedding instructions.
// The patterns are resolved relatively to the `documentation_root`.
// Directories are never matched by these patterns.
// For example, "docs/**/*.md,guides/*.html".
// The default value is "**/*.md,**/*.html".
//
// DocExcludes - a StringList with patterns for filtering documentation files
// which should be excluded from the embedding process.
//
// Separator — a string that's inserted between multiple partitions of a single fragment.
// The default value is "...".
//
// Embeddings — independent configurations for embedding multiple documentation targets.
//
// Info - specifies whether info-level logs should be shown.
//
// Stacktrace - specifies whether error stack traces should be shown.
//
// ConfigPath — a path to a yaml configuration file which contains roots or embeddings.
//
// Mode — defines the mode of embed-code execution.
// Config contains user-specified embed-code settings.
type Config struct {
// BaseCodePaths contains directories with source code files.
BaseCodePaths _type.NamedPathList `yaml:"code-path"`
BaseDocsPath string `yaml:"docs-path"`
DocIncludes _type.StringList `yaml:"doc-includes"`
DocExcludes _type.StringList `yaml:"doc-excludes"`
Separator string `yaml:"separator"`
Embeddings []EmbeddingConfig `yaml:"embeddings"`
Info bool `yaml:"info"`
Stacktrace bool `yaml:"stacktrace"`
ConfigPath string
Mode string

// BaseDocsPath is the root directory containing documentation files.
BaseDocsPath string `yaml:"docs-path"`

// DocIncludes contains patterns selecting documentation files to process.
// Patterns are resolved relative to the documentation root.
// For example, "docs/**/*.md,guides/*.html". The default is "**/*.md,**/*.html".
DocIncludes _type.StringList `yaml:"doc-includes"`

// DocExcludes contains patterns selecting documentation files to skip.
DocExcludes _type.StringList `yaml:"doc-excludes"`

// Separator is inserted between multiple partitions of one fragment.
// The default is "...".
Separator string `yaml:"separator"`

// Embeddings contains independent embedding target configurations.
Embeddings []EmbeddingConfig `yaml:"embeddings"`

// Info reports whether info-level logs should be shown.
Info bool `yaml:"info"`

// Stacktrace reports whether panic stack traces should be shown.
Stacktrace bool `yaml:"stacktrace"`

// ConfigPath is the path to the YAML configuration file.
ConfigPath string

// Mode selects check or embed execution.
Mode string
}

// EmbeddingConfig contains a complete configuration for one embedding target.
type EmbeddingConfig struct {
Name string `yaml:"name"`
CodePaths _type.NamedPathList `yaml:"code-path"`
DocsPath string `yaml:"docs-path"`
DocIncludes _type.StringList `yaml:"doc-includes"`
DocExcludes _type.StringList `yaml:"doc-excludes"`
Separator string `yaml:"separator"`
// Name identifies the embedding target.
Name string `yaml:"name"`

// CodePaths contains directories with source code files.
CodePaths _type.NamedPathList `yaml:"code-path"`

// DocsPath is the root directory containing documentation files.
DocsPath string `yaml:"docs-path"`

// DocIncludes contains patterns selecting documentation files to process.
DocIncludes _type.StringList `yaml:"doc-includes"`

// DocExcludes contains patterns selecting documentation files to skip.
DocExcludes _type.StringList `yaml:"doc-excludes"`

// Separator is inserted between multiple partitions of one fragment.
Separator string `yaml:"separator"`
}

// EmbedCodeSamplesResult is result of the EmbedCodeSamples method.
//
// EmbedAllResult the result of embedding code fragments in the documentation.
// EmbedCodeSamplesResult contains the result of an EmbedCodeSamples operation.
type EmbedCodeSamplesResult struct {
// EmbedAllResult contains the underlying embedding result.
embedding.EmbedAllResult
}

const (
// ModeCheck checks whether documentation snippets are up-to-date.
ModeCheck = "check"

// ModeEmbed rewrites documentation snippets from source code.
ModeEmbed = "embed"
)

// CheckCodeSamples returns documentation files that are not up-to-date with code files.
//
// config — a configuration for checking code samples.
// Parameters:
// config - provides embedding configuration.
//
// Returns:
// []string - stale documentation file paths.
// error - when selected documents fail to process.
func CheckCodeSamples(config configuration.Configuration) ([]string, error) {
return embedding.CheckUpToDate(config)
}

// EmbedCodeSamples embeds code fragments in documentation files.
//
// config — a configuration for embedding.
// Parameters:
// config - provides embedding configuration.
//
// Returns:
// EmbedCodeSamplesResult - embedding result.
// error - when selected documents fail to process or write.
func EmbedCodeSamples(config configuration.Configuration) (EmbedCodeSamplesResult, error) {
embeddingResult, err := embedding.EmbedAll(config)
if err != nil {
Expand All @@ -117,9 +135,9 @@ func EmbedCodeSamples(config configuration.Configuration) (EmbedCodeSamplesResul
}, nil
}

// ReadArgs reads user-specified args from the command line.
// ReadArgs reads user-specified command-line args.
//
// Returns Config struct filled with the corresponding args.
// Returns command-line configuration.
func ReadArgs() Config {
codePath := flag.String("code-path", "", "a path to a root directory with code files")
docsPath := flag.String("docs-path", "", "a path to a root directory with docs files")
Expand Down Expand Up @@ -152,11 +170,14 @@ func ReadArgs() Config {
}
}

// FillArgsFromConfigFile fills config with the values read from config file.
// FillArgsFromConfigFile fills args with values read from the configured YAML file.
//
// args — Config struct with user-provided args.
// Parameters:
// args - provides the config file path and command-line defaults.
//
// Returns filled Config.
// Returns:
// Config - merged configuration.
// error - when the YAML file cannot be read or decoded.
func FillArgsFromConfigFile(args Config) (Config, error) {
configFields, err := readConfigFields(args.ConfigPath)
if err != nil {
Expand Down Expand Up @@ -187,9 +208,12 @@ func FillArgsFromConfigFile(args Config) (Config, error) {
return args, nil
}

// BuildEmbedCodeConfiguration generates and returns a configuration based on provided userArgs.
// BuildEmbedCodeConfiguration builds normalized embedding configurations from user args.
//
// userArgs — a Config with user-provided args.
// Parameters:
// userArgs - provides command-line and YAML configuration values.
//
// Returns normalized embedding configurations.
func BuildEmbedCodeConfiguration(userArgs Config) []configuration.Configuration {
embedCodeConfigs := make([]configuration.Configuration, 0)

Expand Down Expand Up @@ -278,7 +302,12 @@ func sourceFoldersLabel(paths _type.NamedPathList) string {
return "Source code folders: " + strings.Join(labels, ", ")
}

// parseListArgument returns a list of strings from given comma-separated string listArgument.
// parseListArgument splits a comma-separated command-line argument.
//
// Parameters:
// listArgument - provides a comma-separated string.
//
// Returns parsed non-empty values.
func parseListArgument(listArgument string) []string {
splitArgs := strings.Split(listArgument, ",")
parsedArgs := make([]string, 0)
Expand All @@ -291,11 +320,14 @@ func parseListArgument(listArgument string) []string {
return parsedArgs
}

// readConfigFields reads the provided config file and returns parsed fields.
// readConfigFields reads and parses a YAML configuration file.
//
// configFilePath — a path to a yaml configuration file.
// Parameters:
// configFilePath - provides the path to a YAML configuration file.
//
// Returns a filled ConfigFields struct.
// Returns:
// Config - parsed configuration fields.
// error - when the file cannot be read or decoded.
func readConfigFields(configFilePath string) (Config, error) {
content, err := os.ReadFile(configFilePath)
if err != nil {
Expand Down
Loading
Loading