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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).

### Added

- The `agentskills` provider installs Agent Skills-compatible `SKILL.md` files under `.agents/skills/<Name>/SKILL.md`, with `agents` as an alias for `--provider agents` and an Agent Skills frontmatter whitelist.
- `forge adopt <url>` fetches an upstream HTTPS artifact (or `file://` fixture), applies the `align` transform into a module skill or companion file, and writes an `adopt/v1` provenance sidecar with the upstream digest pin.
- `forge find "<query>"` scans local modules, discovered repos, and already-cached watchlist sources for skills, agents, and rules, ranking matches by name, trigger text, and description with optional JSON output.
- `forge config` prints the resolved forge ontology from `~/.config/forge/config.yaml`, with `FORGE_*` environment overrides taking precedence over file values and built-in defaults. The legacy `project.yaml` file remains as a deprecated fallback for one release.
- `forge exec <skill>` runs skill-bundled scripts through a small synchronous runtime table (`uv run`, `bash`, `deno run`, `node`), injects `FORGE_*`/`INPUT_*` environment, supports JSON stdin/stdout wrapping, dry-runs, and output schema validation.
- Unknown `forge <verb>` commands now dispatch to external `forge-<verb>` scripts from the module `commands/` directory, configured extension directories, or `PATH`, keeping new capabilities out of the Rust kernel.
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ chrono = "0.4"
regex = "1"
console = "0.15"
dirs = "6"
ureq = { version = "3", default-features = false, features = ["rustls"] }

# git
gix = { version = "0.66", default-features = false, features = ["blocking-network-client", "blocking-http-transport-reqwest-rust-tls", "worktree-mutation"] }
Expand Down
11 changes: 11 additions & 0 deletions defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,17 @@ providers:
fast: [gemini-2.5-flash]
light: [gemini-2.0-flash]

agentskills:
target: ".agents"
aliases:
- agents
assembly:
- strip-links
keep_fields:
agents: [name, description]
skills: [name, description, license, compatibility, metadata, allowed-tools]
rules: []

codex:
target: ".codex"
model: gpt-5.5
Expand Down
67 changes: 67 additions & 0 deletions docs/decisions/CLI-0016 Forge Adopt Provenance Mechanism.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
title: "Forge Adopt Provenance Mechanism"
description: "forge adopt fetches upstream artifacts synchronously and records adopt/v1 provenance"
type: adr
category: cli
tags:
- cli
- adopt
- provenance
- dependencies
status: accepted
created: 2026-07-09
updated: 2026-07-09
author: "@N4M3Z"
project: forge-cli
related:
- "ASSEMBLY-0010 Copy Provenance"
- "CLI-0011 Watchlist Monitored-Source Registry"
- "RUST-0006 Synchronous Core"
responsible: ["@N4M3Z"]
accountable: ["@N4M3Z"]
consulted: []
informed: []
upstream: []
---

# Forge Adopt Provenance Mechanism

## Context and Problem Statement

Forge modules need a repeatable way to bring in useful upstream skills without losing the source URL, fetched digest, or local transform history. Manual adoption leaves review notes outside the repository and makes later drift checks dependent on memory. The command also needs to fit Forge's synchronous CLI architecture and the existing source-side `.provenance/` sidecar scan.

## Decision Drivers

- Preserve upstream attribution and digest pins in typed provenance sidecars
- Keep the command synchronous and available under the default `full` feature
- Avoid network access in unit tests
- Reject path traversal before writing into a module
- Use a small blocking HTTP client instead of adding an async runtime

## Considered Options

1. **Keep adoption as a manual skill workflow.** This keeps Rust smaller, but provenance depends on a human writing matching sidecars correctly.
2. **Use `reqwest`.** It is familiar and already appears transitively through `gix`, but direct use would add an async-first client surface or extra blocking feature choices.
3. **Use `ureq` v3 with rustls.** It provides a blocking API, follows redirects by configuration, and reuses the rustls ecosystem already present through the git stack.

## Decision Outcome

Chosen option: **Option 3**.

`forge adopt <url>` classifies anchored HTTPS, GitHub blob/raw, and hermetic `file://` fixture URLs. It fetches bytes through `ureq` for HTTPS, rejects non-UTF-8 bodies, applies the `align` transform, writes the artifact under the requested module, and records a source-side `.provenance/<stem>.yaml` sidecar. GitHub URLs must carry a full 40-hex commit in the URL before Forge records `externalParameters.upstream_commit`; plain HTTPS sources record an empty commit field.

The sidecar uses the existing manifest provenance types with `buildType: adopt/v1`, `externalParameters.upstream_url`, `externalParameters.transforms_applied: ["align"]`, the landed subject digest, and one `resolvedDependencies` entry named `upstream` containing the fetched-body digest. Unit tests inject fetched bytes directly, and an ignored smoke can cover a real hosted skill separately.

## Consequences

- Adoption becomes reproducible enough for source-side provenance verification and drift detection.
- `ureq` adds a direct dependency, but it avoids tokio in `full` and keeps HTTP behavior blocking.
- Plain HTTPS adoption pins content by digest but cannot independently prove a source commit.
- GitHub branch or tag URLs are rejected until Forge has a commit-resolution path that does not weaken the pin.
- The dashboard's private attribution model remains separate from the manifest provenance model.

## More Information

- [ASSEMBLY-0010 Copy Provenance](ASSEMBLY-0010%20Copy%20Provenance.md)
- [CLI-0011 Watchlist Monitored-Source Registry](CLI-0011%20Watchlist%20Monitored-Source%20Registry.md)
- [RUST-0006 Synchronous Core](RUST-0006%20Synchronous%20Core.md)
64 changes: 64 additions & 0 deletions docs/decisions/CLI-0017 Agentskills Provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: "Agentskills Provider"
description: "The Agent Skills provider uses the agentskills key and deploys to .agents"
type: adr
category: cli
tags:
- cli
- providers
- agentskills
- assembly
status: accepted
created: 2026-07-09
updated: 2026-07-09
author: "@N4M3Z"
project: forge-cli
related:
- "ASSEMBLY-0011 Provider and Model Identifiers"
responsible: ["@N4M3Z"]
accountable: ["@N4M3Z"]
consulted: []
informed: []
upstream:
- "https://agentskills.io/specification"
---

# Agentskills Provider

## Context and Problem Statement

Agent Skills-compatible clients load skill directories from `.agents`, with each skill represented by a `SKILL.md` file and YAML frontmatter. Forge already has a generic provider deployment model where content lands at `<target>/<kind>/<relative>`, so `.agents` support should be provider data rather than another path-specific branch in deployment code. The provider name also participates in qualifier directory discovery for `rules/` and `agents/`, which creates a collision if the provider key is literally `agents`.

## Decision Drivers

- Add `.agents` deployment without provider-specific path code
- Preserve `forge install --provider agents` as a user-facing alias
- Avoid treating `rules/agents/` or `agents/agents/` as provider qualifier directories
- Keep Agent Skills frontmatter compatible with the published specification
- Avoid adding new assembly transforms

## Considered Options

1. **Name the provider `agents`.** This matches the target concept, but it makes `agents` a valid qualifier directory for non-skill content and can swallow ordinary nested content.
2. **Name the provider `agentskills` with alias `agents`.** This avoids qualifier collision while preserving the expected install selector.
3. **Special-case `.agents` in deployment code.** This works, but duplicates behavior already covered by provider `target` data.

## Decision Outcome

Chosen option: **Option 2**.

Forge defines provider key `agentskills`, target `.agents`, alias `agents`, and `assembly: [strip-links]`. The generic deployment path places a skill at `.agents/skills/<Name>/SKILL.md` with no path-code changes. Qualifier discovery sees `agentskills` as the provider name and never sees the alias, so `rules/agents/` is not a provider qualifier directory.

The Agent Skills specification requires `name` and `description`. It also recognizes top-level `license`, `compatibility`, `metadata`, and experimental `allowed-tools`; `version` is shown as `metadata.version`, not a top-level field. The provider keeps the recognized top-level fields and does not invent a top-level `version` field.

## Consequences

- Users can select the provider with either `agentskills` or `agents`.
- Existing provider assembly and deployment code handles the target path.
- The provider whitelist may need revision if the Agent Skills specification changes.
- Optional fields survive when authored, but unsupported Forge-specific fields are still stripped.

## More Information

- [Agent Skills specification](https://agentskills.io/specification)
- [ASSEMBLY-0011 Provider and Model Identifiers](ASSEMBLY-0011%20Provider%20and%20Model%20Identifiers.md)
Loading