Skip to content

Commit 96e88ee

Browse files
authored
docs: fix spec audit — add Public API, Usage Examples, and Dependencies to 17 packages (#30155)
1 parent 59f61d0 commit 96e88ee

21 files changed

Lines changed: 520 additions & 33 deletions

File tree

.github/workflows/daily-model-inventory.lock.yml

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/agentdrain/README.md

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ In GitHub Agentic Workflows, `agentdrain` processes `AgentEvent` records emitted
1010
1. Build a model of normal behavior by training on events from successful runs.
1111
2. Detect anomalies in new runs by comparing events against the learned model.
1212

13-
## Types
13+
## Public API
14+
15+
### Types
1416

1517
### `Config`
1618

@@ -95,7 +97,7 @@ type AnomalyReport struct {
9597
}
9698
```
9799

98-
## Core Components
100+
### Core Components
99101

100102
### `Miner`
101103

@@ -210,6 +212,45 @@ type SnapshotCluster struct {
210212

211213
These types are returned and consumed by `SaveSnapshots` / `LoadSnapshots` and are serialized as JSON.
212214

215+
## Usage Examples
216+
217+
```go
218+
import "github.com/github/gh-aw/pkg/agentdrain"
219+
220+
// Create a coordinator with default config
221+
cfg := agentdrain.DefaultConfig()
222+
stages := []string{"plan", "tool_call", "finish"}
223+
coord, err := agentdrain.NewCoordinator(cfg, stages)
224+
if err != nil {
225+
panic(err)
226+
}
227+
228+
// Load pre-trained weights
229+
if err := coord.LoadDefaultWeights(); err != nil {
230+
panic(err)
231+
}
232+
233+
// Analyze an incoming agent event
234+
evt := agentdrain.AgentEvent{
235+
Stage: "tool_call",
236+
Fields: map[string]string{"tool": "read_file", "path": "/workspace/main.go"},
237+
}
238+
result, report, err := coord.AnalyzeEvent(evt)
239+
if err != nil {
240+
panic(err)
241+
}
242+
if report.IsNewTemplate {
243+
fmt.Printf("New behavior pattern detected (score=%.2f): %s\n",
244+
report.AnomalyScore, report.Reason)
245+
}
246+
```
247+
248+
## Dependencies
249+
250+
**Internal**:
251+
- `pkg/logger` — debug logging
252+
- `pkg/sliceutil` — slice utilities for cluster management
253+
213254
## Default Weights
214255

215256
The package embeds a set of default trained weights (in `data/`) via `//go:embed`. Call `coord.LoadDefaultWeights()` to initialize the coordinator with pre-trained cluster weights rather than starting cold.

pkg/cli/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,15 @@ err := cli.RunHealth(cli.HealthConfig{
446446
- `pkg/console` — terminal output formatting
447447
- `pkg/logger` — structured debug logging
448448
- `pkg/constants` — engine names, job names, feature flags
449+
- `pkg/agentdrain` — Drain log anomaly detection for audit analysis
450+
- `pkg/envutil` — environment variable reading with bounds validation
451+
- `pkg/semverutil` — semantic version comparison for dependency checks
452+
- `pkg/sliceutil` — slice utilities
453+
- `pkg/stats` — incremental statistics for health metrics
454+
- `pkg/styles` — terminal color styles and lipgloss configuration
455+
- `pkg/timeutil` — human-readable duration formatting
456+
- `pkg/tty` — terminal detection
457+
- `pkg/types` — shared MCP server configuration types
449458
- `pkg/stringutil`, `pkg/fileutil`, `pkg/gitutil`, `pkg/repoutil` — utilities
450459

451460
**External**:

pkg/console/README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,33 @@ This package follows Charmbracelet best practices for terminal UI:
3131
- **Boxes**: 2 character horizontal padding, 0-1 vertical padding
3232
- **Info sections**: 2 character left padding for consistent indentation
3333

34+
## Public API
35+
36+
The following components and functions are exported by the `console` package:
37+
38+
| Export | Kind | Description |
39+
|--------|------|-------------|
40+
| `NewSpinner` | func | Creates a new animated spinner |
41+
| `NewProgressBar` | func | Creates a determinate progress bar |
42+
| `NewIndeterminateProgressBar` | func | Creates an indeterminate progress bar |
43+
| `RenderStruct` | func | Renders a Go struct to a styled terminal string |
44+
| `RenderTable` | func | Renders a formatted table string |
45+
| `RenderTree` | func | Renders a tree-node hierarchy |
46+
| `RenderTitleBox` / `RenderErrorBox` / `RenderInfoSection` | funcs | Section rendering helpers |
47+
| `RenderComposedSections` | func | Composes and prints multiple sections |
48+
| `FormatSuccessMessage` / `FormatInfoMessage` / `FormatWarningMessage` / `FormatErrorMessage` | funcs | Styled status message formatting |
49+
| `FormatCommandMessage` / `FormatProgressMessage` / `FormatVerboseMessage` | funcs | Additional message styles |
50+
| `FormatError` | func | Renders a structured `CompilerError` with context |
51+
| `FormatErrorChain` | func | Renders a wrapped-error chain |
52+
| `FormatErrorWithSuggestions` | func | Error message with actionable suggestions |
53+
| `ConfirmAction` | func | Interactive yes/no confirmation |
54+
| `ShowInteractiveList` | func | Interactive single-selection list |
55+
| `PromptInput` / `PromptSecretInput` | funcs | Text and secret input prompts |
56+
| `LogVerbose` | func | Conditional verbose logging |
57+
| `FormatFileSize` / `FormatNumber` | funcs | Human-readable byte and integer formatting |
58+
| `IsAccessibleMode` | func | Detects accessibility mode |
59+
| `CompilerError` / `ErrorPosition` / `TableConfig` / `TreeNode` | types | Supporting data types |
60+
3461
## Spinner Component
3562

3663
The `Spinner` component provides animated visual feedback during long-running operations with automatic TTY detection and accessibility support.
@@ -794,6 +821,59 @@ if console.IsAccessibleMode() {
794821
}
795822
```
796823

824+
## Usage Examples
825+
826+
```go
827+
import (
828+
"fmt"
829+
"os"
830+
"github.com/github/gh-aw/pkg/console"
831+
)
832+
833+
// Display a spinner during a long-running operation
834+
spinner := console.NewSpinner("Compiling workflows...")
835+
spinner.Start()
836+
// ... do work ...
837+
spinner.StopWithMessage("✓ Done!")
838+
839+
// Format status messages (always write to stderr)
840+
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Workflow compiled successfully"))
841+
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Processing 3 files..."))
842+
fmt.Fprintln(os.Stderr, console.FormatWarningMessage("Network access is unrestricted"))
843+
fmt.Fprintln(os.Stderr, console.FormatErrorMessage("File not found: workflow.md"))
844+
845+
// Render a table
846+
table := console.RenderTable(console.TableConfig{
847+
Headers: []string{"Name", "Status"},
848+
Rows: [][]string{
849+
{"build", "success"},
850+
{"test", "failure"},
851+
},
852+
Title: "Job Results",
853+
})
854+
fmt.Print(table)
855+
856+
// Interactive confirmation
857+
confirmed, err := console.ConfirmAction("Delete all compiled workflows?", "Yes, delete", "Cancel")
858+
if err != nil || !confirmed {
859+
return
860+
}
861+
```
862+
863+
## Dependencies
864+
865+
**Internal**:
866+
- `pkg/logger` — debug-level console logging
867+
- `pkg/styles` — adaptive color constants and pre-configured lipgloss styles
868+
- `pkg/tty` — terminal detection for spinner and progress bar
869+
870+
**External**:
871+
- `charm.land/lipgloss/v2` — terminal styling and layout
872+
- `charm.land/bubbles/v2/spinner` — spinner animation
873+
- `charm.land/bubbles/v2/progress` — progress bar
874+
- `charm.land/bubbletea/v2` — terminal UI event loop
875+
- `charm.land/huh/v2` — interactive form components
876+
797877
---
798878

799879
*This specification is automatically maintained by the [spec-extractor](../../.github/workflows/spec-extractor.md) workflow.*

pkg/constants/README.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ The package is organized into focused files:
1616
| `url_constants.go` | URL semantic types, well-known URLs, documentation URLs |
1717
| `version_constants.go` | Default version strings and minimum version constraints |
1818

19-
## Semantic Types
19+
## Public API
20+
21+
### Semantic Types
2022

2123
The package uses typed aliases to prevent mixing unrelated string or integer values:
2224

@@ -441,6 +443,39 @@ constants.DefaultGitHubTools // deprecated: use DefaultGitHubToolsL
441443
constants.DefaultBashTools
442444
```
443445

446+
## Usage Examples
447+
448+
```go
449+
import "github.com/github/gh-aw/pkg/constants"
450+
451+
// Engine constants
452+
engine := constants.CopilotEngine // EngineName("copilot")
453+
fmt.Println(engine.String()) // "copilot"
454+
fmt.Println(engine.IsValid()) // true
455+
456+
// Resolve an engine option for display and secret info
457+
opt := constants.GetEngineOption("copilot")
458+
fmt.Println(opt.Label) // "GitHub Copilot"
459+
fmt.Println(opt.SecretName) // "COPILOT_GITHUB_TOKEN"
460+
461+
// Version constants
462+
fmt.Println(constants.DefaultCopilotVersion)
463+
464+
// Feature flags
465+
fmt.Println(constants.MCPGatewayFeatureFlag.String()) // "mcp-gateway"
466+
467+
// Job / step IDs
468+
fmt.Println(constants.AgentJobName.String()) // "agent"
469+
fmt.Println(constants.CheckMembershipStepID.String()) // "check_membership"
470+
471+
// Runtime paths
472+
fmt.Println(constants.GhAwRootDir) // "${{ runner.temp }}/gh-aw"
473+
fmt.Println(constants.GhAwRootDirShell) // "${RUNNER_TEMP}/gh-aw"
474+
475+
// Dynamic workflow directory (respects GH_AW_WORKFLOWS_DIR)
476+
dir := constants.GetWorkflowDir() // ".github/workflows"
477+
```
478+
444479
## Design Notes
445480

446481
- All semantic types implement `String()` and `IsValid()` to allow consistent validation across the codebase.

pkg/envutil/README.md

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,21 @@ The `envutil` package provides utilities for reading and validating environment
66

77
This package centralizes the pattern of reading integer-valued environment variables, validating them against configured minimum and maximum bounds, and falling back to a default value when the variable is absent or out of range. It emits warning messages to stderr when an invalid value is encountered, following the console formatting conventions of the rest of the codebase.
88

9-
## Usage
9+
## Public API
1010

11-
### GetIntFromEnv
11+
### `GetIntFromEnv(envVar string, defaultValue, minValue, maxValue int, log *logger.Logger) int`
12+
13+
Reads an integer-valued environment variable, validates it against `[minValue, maxValue]`, and returns `defaultValue` when the variable is absent, unparseable, or out of range. A warning is emitted to `os.Stderr` when the value is invalid.
14+
15+
| Parameter | Type | Description |
16+
|-----------|------|-------------|
17+
| `envVar` | `string` | Environment variable name (e.g. `"GH_AW_TIMEOUT"`) |
18+
| `defaultValue` | `int` | Value returned when env var is absent or invalid |
19+
| `minValue` | `int` | Minimum allowed value (inclusive) |
20+
| `maxValue` | `int` | Maximum allowed value (inclusive) |
21+
| `log` | `*logger.Logger` | Optional logger for debug output; pass `nil` to disable |
22+
23+
## Usage Examples
1224

1325
```go
1426
import (
@@ -20,24 +32,22 @@ var log = logger.New("mypackage:config")
2032

2133
// Read GH_AW_MAX_CONCURRENT_DOWNLOADS, constrained to [1, 20], default 5
2234
concurrency := envutil.GetIntFromEnv("GH_AW_MAX_CONCURRENT_DOWNLOADS", 5, 1, 20, log)
35+
36+
// Suppress debug output by passing nil logger
37+
timeout := envutil.GetIntFromEnv("GH_AW_TIMEOUT", 60, 1, 3600, nil)
2338
```
2439

2540
**Behavior**:
2641
- Returns `defaultValue` when the environment variable is not set.
2742
- Returns `defaultValue` and emits a warning when the value cannot be parsed as an integer.
2843
- Returns `defaultValue` and emits a warning when the value is outside `[minValue, maxValue]`.
2944
- Logs the accepted value at debug level when `log` is non-nil.
30-
- Pass `nil` for `log` to suppress debug output.
3145

32-
### Parameters
46+
## Dependencies
3347

34-
| Parameter | Type | Description |
35-
|-----------|------|-------------|
36-
| `envVar` | `string` | Environment variable name (e.g. `"GH_AW_TIMEOUT"`) |
37-
| `defaultValue` | `int` | Value returned when env var is absent or invalid |
38-
| `minValue` | `int` | Minimum allowed value (inclusive) |
39-
| `maxValue` | `int` | Maximum allowed value (inclusive) |
40-
| `log` | `*logger.Logger` | Optional logger for debug output; pass `nil` to disable |
48+
**Internal**:
49+
- `pkg/console` — warning message formatting
50+
- `pkg/logger` — debug logging
4151

4252
## Design Notes
4353

pkg/fileutil/README.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ The `fileutil` package provides utility functions for safe file path validation
66

77
This package focuses on security-conscious file handling: path validation, boundary enforcement, and straightforward file/directory operations. It also provides a cross-platform tar extraction helper.
88

9-
## Functions
9+
## Public API
1010

1111
### Path Validation
1212

@@ -83,6 +83,33 @@ if err != nil {
8383
}
8484
```
8585

86+
## Usage Examples
87+
88+
```go
89+
import "github.com/github/gh-aw/pkg/fileutil"
90+
91+
// Validate and clean a user-supplied path
92+
cleanPath, err := fileutil.ValidateAbsolutePath(userInput)
93+
if err != nil {
94+
return fmt.Errorf("invalid path: %w", err)
95+
}
96+
97+
// Ensure output path stays within workspace
98+
if err := fileutil.MustBeWithin("/workspace", outputPath); err != nil {
99+
return fmt.Errorf("output path escapes workspace: %w", err)
100+
}
101+
102+
// Copy a file
103+
if err := fileutil.CopyFile("source.txt", "destination.txt"); err != nil {
104+
return fmt.Errorf("copy failed: %w", err)
105+
}
106+
```
107+
108+
## Dependencies
109+
110+
**Internal**:
111+
- `pkg/logger` — debug logging
112+
86113
## Design Notes
87114

88115
- All debug output uses `logger.New("fileutil:fileutil")` and `logger.New("fileutil:tar")` and is only emitted when `DEBUG=fileutil:*`.

pkg/gitutil/README.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ This package contains helpers for:
1111
- Finding the root directory of the current Git repository.
1212
- Reading file contents from the `HEAD` commit.
1313

14-
## Functions
14+
## Public API
1515

1616
### Error Classification
1717

@@ -88,6 +88,36 @@ root, _ := gitutil.FindGitRoot()
8888
content, err := gitutil.ReadFileFromHEADWithRoot("pkg/workflow/compiler.go", root)
8989
```
9090

91+
## Usage Examples
92+
93+
```go
94+
import "github.com/github/gh-aw/pkg/gitutil"
95+
96+
// Check for rate-limit errors from GitHub API
97+
if gitutil.IsRateLimitError(err.Error()) {
98+
// Back off and retry
99+
}
100+
101+
// Validate a commit SHA
102+
if gitutil.IsValidFullSHA(commitSHA) {
103+
fmt.Println("Valid 40-character commit SHA")
104+
}
105+
106+
// Find the git repository root
107+
root, err := gitutil.FindGitRoot()
108+
if err != nil {
109+
return fmt.Errorf("not in a git repository: %w", err)
110+
}
111+
112+
// Read a file from the HEAD commit
113+
content, err := gitutil.ReadFileFromHEADWithRoot("go.mod", root)
114+
```
115+
116+
## Dependencies
117+
118+
**Internal**:
119+
- `pkg/logger` — debug logging
120+
91121
## Design Notes
92122

93123
- All debug output uses `logger.New("gitutil:gitutil")` and is only emitted when `DEBUG=gitutil:*`.

0 commit comments

Comments
 (0)