Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5ff6902
fix(intelligence): ignore git directory markers in snapshots
ashwingopalsamy Sep 22, 2026
4381456
fix(intelligence): gate focus facets by declaration kind
ashwingopalsamy Sep 22, 2026
7cb2117
feat(trace): record bounded go_context outcomes
ashwingopalsamy Sep 22, 2026
91522af
fix(test): satisfy release lint gate
ashwingopalsamy Sep 23, 2026
dcee0aa
docs(release): prepare v1.2.0
ashwingopalsamy Sep 23, 2026
283caee
feat(intelligence): map verification evidence to next actions
ashwingopalsamy Sep 23, 2026
67f54b7
docs(release): prepare v1.2.1
ashwingopalsamy Sep 23, 2026
8e65ce1
feat(mcp): expose context next actions in text
ashwingopalsamy Sep 23, 2026
71099dc
fix(intelligence): clarify truncated evidence guidance
ashwingopalsamy Sep 23, 2026
56c2199
docs(intelligence): reconcile reliability guidance
ashwingopalsamy Sep 23, 2026
cbbdffc
docs(eval): record Luna adoption evidence
ashwingopalsamy Sep 23, 2026
6d7b1e9
docs(guidance): refine context refresh workflow
ashwingopalsamy Sep 23, 2026
9e7e4b8
docs(eval): record guidance regression signals
ashwingopalsamy Sep 23, 2026
7b5111c
fix(intelligence): preserve bounded focus evidence
ashwingopalsamy Sep 24, 2026
09b908f
feat(sourceview): add exact branch worktree preview
ashwingopalsamy Sep 27, 2026
298454f
feat(context): add focused retrieval and delivery evidence
ashwingopalsamy Sep 27, 2026
8c737ad
feat(retrieval-eval): add bounded branch corpus screen
ashwingopalsamy Sep 27, 2026
8137b84
docs(product): record retrieval limits and next gates
ashwingopalsamy Sep 27, 2026
718d7c9
fix(ci): resolve branch retrieval lint findings
ashwingopalsamy Sep 27, 2026
b2e75e2
fix(ci): resolve retrieval study lint findings
ashwingopalsamy Sep 27, 2026
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
27 changes: 19 additions & 8 deletions .agents/skills/agentic-go-context/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,28 @@ description: Use agentic-go context before unfamiliar or cross-package Go edits
# Agentic Go Context

For unfamiliar or cross-package Go edits, call `go_context` before editing and
refresh after edits.
refresh after edits. The workflow is snapshot-bound evidence, not a correctness
claim.

1. Start with `base` and one selector: `query`, `symbol_ref`, source
1. Start with `base` and exactly one selector: `query`, `symbol_ref`, source
`file`+`line`+`column`, or `focus_file`/`focus_package`. Selectors are
mutually exclusive.
2. After editing, refresh with `base` and `previous_pack_id` only. Omit old
selectors and Symbol Refs.
3. Stale rejection is expected: stop and select current evidence; never bypass
it.
4. Use the result for impact and verification applicability. Treat impact and
2. Symbol Refs are opaque byte strings. Copy them exactly. Never decode, edit,
shorten, reconstruct, or re-encode one.
3. File coordinates must point to the declaration identifier itself, never
whitespace, a line start, a comment, or a local variable.
4. If a result is ambiguous, copy one returned current candidate or issue a
fresh query/file selector. Do not repeat the same broad query.
5. A selector failure produces no evidence. Do not retry the same selector;
recover with fresh evidence. Stale rejection is expected and must not be
bypassed.
6. Finish each batch of edits and formatting before refreshing. Refresh with
`base` and `previous_pack_id` only; omit old selectors and Symbol Refs.
Refresh again after further edits or stale-snapshot rejection; avoid
redundant refreshes while the snapshot is unchanged.
7. Use the result for impact and verification applicability. Treat impact and
reverse-dependency evidence as planning guidance, not authorization to edit
affected packages; edit only the smallest task owner within supplied
path/package scope. Skip trivial edits and preserve uncertainty when
evidence is unavailable.
evidence is unavailable. Context does not execute checks or prove
correctness.
33 changes: 32 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,35 @@ All notable changes to this project are documented here. The format follows

## [Unreleased]

## [1.2.1] - 2026-09-23

### Added

- Deterministic `go_context` evidence-to-action guidance for verification,
finding inspection, unavailable evidence, and bounded passing checks.

### Fixed

- Stale, incomplete, truncated, mismatched, and invalid-location evidence now
fails closed before producing current action guidance.

## [1.2.0] - 2026-09-23

### Added

- Bounded opt-in `go_context` trace outcomes with privacy-preserving aggregate
summaries and cancellation, deadline, and internal failure categories.
- Focus-facet evidence tests covering callable declarations, type declarations,
variables and fields, unsupported capabilities, cancellation, and stale
references.

### Fixed

- Snapshot observation now ignores Git directory markers emitted by status
commands while preserving strict file and content validation.
- Focus expansion now reports applicability and evidence states accurately and
preserves provider and snapshot errors.

## [1.1.0] - 2026-09-07

### Added
Expand Down Expand Up @@ -75,6 +104,8 @@ All notable changes to this project are documented here. The format follows
- Workspace containment, bounded execution, event-driven progress, and
optional privacy-preserving local traces.

[Unreleased]: https://github.com/agentic-mcps/go/compare/v1.1.0...HEAD
[Unreleased]: https://github.com/agentic-mcps/go/compare/v1.2.1...HEAD
[1.2.1]: https://github.com/agentic-mcps/go/releases/tag/v1.2.1
[1.2.0]: https://github.com/agentic-mcps/go/releases/tag/v1.2.0
[1.1.0]: https://github.com/agentic-mcps/go/releases/tag/v1.1.0
[1.0.0]: https://github.com/agentic-mcps/go/releases/tag/v1.0.0
38 changes: 33 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,20 @@
<a href="#install"><img src="assets/brand/pills/install.svg" alt="Install agentic-go"></a>
<a href="#connect"><img src="assets/brand/pills/mcp-setup.svg" alt="Connect MCP"></a>
<a href="https://agentic-mcps.github.io/go/docs/"><img src="assets/brand/pills/docs.svg" alt="Read docs"></a>
<a href="https://github.com/agentic-mcps/go/releases/tag/v1.1.0"><img src="assets/brand/pills/release.svg" alt="v1.1.0 release"></a>
<a href="https://github.com/agentic-mcps/go/releases/tag/v1.2.1"><img src="assets/brand/pills/release.svg" alt="v1.2.1 release"></a>
</p>

<p align="center"><a href="https://agentic-mcps.github.io/go/">Website</a> · <a href="https://agentic-mcps.github.io/go/docs/">Docs</a> · <a href="#install">Install</a> · <a href="#connect">Connect</a> · <a href="#workflow">Workflow</a> · <a href="#capabilities">Capabilities</a> · <a href="#faq">FAQ</a></p>

`agentic-go` is a local Go MCP server and CLI. It gives an external coding agent semantic context, change continuity, guarded refactoring, and executed verification without embedding an LLM or becoming an agent framework.

The v1.1.0 server exposes 15 MCP tools: the frozen v1 surface of 14 tools plus the additive `go_context` tool under `agentic.focus/v1`. The seven resources, resource template, six prompts, and frozen v1 schemas remain unchanged.
The [product north star](docs/go-intelligence-north-star.md) targets Go engineers
using agents throughout understanding, editing, debugging, verification, and
review. It distinguishes current capabilities from planned workflow work and
unproven benefits across models. See the
[continuation handoff](docs/continuation/go-intelligence.md) for current status.

The v1.2.1 server exposes 15 MCP tools: the frozen v1 surface of 14 tools plus the additive `go_context` tool under `agentic.focus/v1`. This patch release makes the edit, refresh, verify, and inspect handoff explicit while preserving snapshot lineage and fail-closed evidence. The seven resources, resource template, six prompts, and frozen v1 schemas remain unchanged.

## Install

Expand All @@ -28,7 +34,7 @@ brew install agentic-mcps/tap/agentic-go
agentic-go --version
```

That installs `agentic-go`, the pinned `agentic-go-gopls` companion, and `agentic-go-vet`. The Homebrew tap is maintained separately; the signed v1.1.0 release archive and checksum installer below are the canonical versioned distribution path.
That installs `agentic-go`, the pinned `agentic-go-gopls` companion, and `agentic-go-vet`. The Homebrew tap is maintained separately; the signed v1.2.1 release archive and checksum installer below are the canonical versioned distribution path.

For an agent workflow, install the binary first, then print the client-native
MCP entry for the current workspace:
Expand All @@ -44,8 +50,8 @@ edit your client configuration.
<summary>Install from the release archive instead</summary>

```sh
curl -fsSL https://raw.githubusercontent.com/agentic-mcps/go/v1.1.0/scripts/install.sh \
| bash -s -- 1.1.0
curl -fsSL https://raw.githubusercontent.com/agentic-mcps/go/v1.2.1/scripts/install.sh \
| bash -s -- 1.2.1
```

The installer places the binaries in `~/.local/bin` and verifies the release checksum before replacing them.
Expand Down Expand Up @@ -106,6 +112,28 @@ For focused context before an edit, an MCP client can call `go_context` with the
agentic-go context --base origin/main --query Worker --format text
```

### Branch source-view preview

The development branch also includes an explicit source-view command for
checking a branch in its own exact Git worktree:

```sh
agentic-go source-view --workspace "$PWD" --branch feature/example \
--output ../agentic-go-feature-example --format json
agentic-go mcp-config --client codex --workspace ../agentic-go-feature-example
```

Without `--branch`, it selects local `main`, or the configured
`origin/HEAD` when `main` is absent. Add `--include-dirty` only when the
source checkout's `HEAD` is exactly the selected commit; it carries staged,
unstaged, and regular untracked changes into the view. The output names the
branch ref, commit, tree, and any checkout limitations. Configure the agent
with the exact view root so snapshot checks can reject a branch that moved.
The source view is a visible detached worktree. This preview does not create a
persistent index or automatically switch a running MCP server, and it reports
uninitialized submodules as incomplete. External `go.work` or local
`replace` inputs are not captured.

## Capabilities

| Area | What the agent gets |
Expand Down
4 changes: 2 additions & 2 deletions assets/brand/pills/release.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions cmd/agentic-go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ func run(args []string) int {
return runVerify(args[1:], os.Stdout, os.Stderr)
case "context":
return runContext(args[1:], os.Stdout, os.Stderr)
case "source-view":
return runSourceView(args[1:], os.Stdout, os.Stderr)
case "doctor":
return runDoctor(args[1:], os.Stdout, os.Stderr, defaultDoctorDependencies())
case "mcp-config":
Expand Down
71 changes: 71 additions & 0 deletions cmd/agentic-go/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/agentic-mcps/go/internal/changeimpact"
"github.com/agentic-mcps/go/internal/execution"
"github.com/agentic-mcps/go/internal/intelligence"
"github.com/agentic-mcps/go/internal/sourceview"
"github.com/agentic-mcps/go/internal/verification"
"github.com/agentic-mcps/go/internal/workspace"
)
Expand Down Expand Up @@ -52,6 +53,76 @@ func TestRunContextValidatesArgumentsBeforeWorkspaceSetup(t *testing.T) {
}
}

func TestRunSourceViewSelectsDefaultAndExplicitBranches(t *testing.T) {
parent := t.TempDir()
repository := filepath.Join(parent, "repo")
if err := os.Mkdir(repository, 0o755); err != nil {
t.Fatal(err)
}
cliGit(t, repository, "init", "-b", "main")
cliGit(t, repository, "config", "user.name", "Fixture")
cliGit(t, repository, "config", "user.email", "fixture@example.test")
cliWrite(t, repository, "go.mod", "module example.test/sourceviewcli\n\ngo 1.25.0\n")
cliWrite(t, repository, "main.go", "package fixture\n\nfunc Branch() string { return \"main\" }\n")
cliGit(t, repository, "add", ".")
cliGit(t, repository, "-c", "commit.gpgsign=false", "commit", "-m", "main")
mainCommit := cliGit(t, repository, "rev-parse", "HEAD")
cliGit(t, repository, "checkout", "-b", "feature")
cliWrite(t, repository, "main.go", "package fixture\n\nfunc Branch() string { return \"feature\" }\n")
cliGit(t, repository, "add", ".")
cliGit(t, repository, "-c", "commit.gpgsign=false", "commit", "-m", "feature")
featureCommit := cliGit(t, repository, "rev-parse", "HEAD")
cliGit(t, repository, "checkout", "main")

mainPath := filepath.Join(parent, "main-view")
var stdout, stderr bytes.Buffer
if exit := runSourceView([]string{"--workspace", repository, "--output", mainPath, "--format", "json"}, &stdout, &stderr); exit != 0 {
t.Fatalf("default source-view exit=%d stderr=%q stdout=%q", exit, stderr.String(), stdout.String())
}
var mainView map[string]any
if err := json.Unmarshal(stdout.Bytes(), &mainView); err != nil {
t.Fatalf("decoding default source view: %v\n%s", err, stdout.String())
}
if mainView["ref"] != "refs/heads/main" || mainView["commit"] != mainCommit || mainView["schema_version"] != sourceview.SchemaVersion {
t.Fatalf("default source view = %#v", mainView)
}
if got := cliGit(t, repository, "branch", "--show-current"); got != "main" {
t.Fatalf("source checkout branch = %q, want main", got)
}

featurePath := filepath.Join(parent, "feature-view")
stdout.Reset()
stderr.Reset()
if exit := runSourceView([]string{"--workspace", repository, "--branch", "feature", "--output", featurePath, "--format", "json"}, &stdout, &stderr); exit != 0 {
t.Fatalf("feature source-view exit=%d stderr=%q stdout=%q", exit, stderr.String(), stdout.String())
}
var featureView map[string]any
if err := json.Unmarshal(stdout.Bytes(), &featureView); err != nil {
t.Fatalf("decoding feature source view: %v\n%s", err, stdout.String())
}
resolvedParent, err := filepath.EvalSymlinks(parent)
if err != nil {
t.Fatal(err)
}
if featureView["ref"] != "refs/heads/feature" || featureView["commit"] != featureCommit || featureView["view_path"] != filepath.Join(resolvedParent, "feature-view") {
t.Fatalf("feature source view = %#v", featureView)
}
contents, err := os.ReadFile(filepath.Join(featurePath, "main.go"))
if err != nil || !strings.Contains(string(contents), `return "feature"`) {
t.Fatalf("feature worktree contents = %q, error = %v", contents, err)
}
}

func TestRunSourceViewRequiresExplicitNewOutputPath(t *testing.T) {
var stdout, stderr bytes.Buffer
if exit := runSourceView(nil, &stdout, &stderr); exit != 2 {
t.Fatalf("exit = %d, want 2", exit)
}
if stdout.Len() != 0 || !strings.Contains(stderr.String(), "--output is required") {
t.Fatalf("stdout=%q stderr=%q", stdout.String(), stderr.String())
}
}

func TestContextJSONAndTextRenderSameFocusIdentity(t *testing.T) {
result := intelligence.FocusResult{SchemaVersion: intelligence.FocusSchemaVersion, Snapshot: intelligence.SnapshotRef{ID: "snapshot-current"}, Change: verification.Change{Files: []verification.ChangedFile{}, Declarations: []verification.ChangedDeclaration{}, FilesTotal: 1}, Impact: verification.Impact{Packages: []verification.ImpactedPackage{}, PackagesTotal: 2}, Risks: []verification.RiskArea{}, Uncertainties: []verification.Uncertainty{}, Verification: intelligence.VerificationApplicability{Reasons: []string{"snapshot differs"}, NextAction: "request verification", Present: true}, Complete: true, PackID: strings.Repeat("a", 64), Refresh: &intelligence.FocusRefresh{PreviousPackID: strings.Repeat("b", 64), Status: "replaced", Message: "refreshed"}}
var jsonOutput bytes.Buffer
Expand Down
89 changes: 89 additions & 0 deletions cmd/agentic-go/source_view.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package main

import (
"context"
"encoding/json"
"flag"
"fmt"
"io"
"os"
"os/signal"
"strings"
"syscall"
"time"

"github.com/agentic-mcps/go/internal/execution"
"github.com/agentic-mcps/go/internal/sourceview"
"github.com/agentic-mcps/go/internal/workspace"
)

func runSourceView(args []string, stdout, stderr io.Writer) int {
flags := flag.NewFlagSet("agentic-go source-view", flag.ContinueOnError)
flags.SetOutput(stderr)
workspacePath := flags.String("workspace", ".", "Git repository root containing the Go workspace")
branch := flags.String("branch", "", "local branch or full refs/heads or refs/remotes ref; defaults to main")
outputPath := flags.String("output", "", "new visible worktree directory outside the source repository")
includeDirty := flags.Bool("include-dirty", false, "overlay staged, unstaged, and regular untracked files when source HEAD exactly matches the selected branch")
format := flags.String("format", "text", "output format: text or json")
if err := flags.Parse(args); err != nil {
return 2
}
if flags.NArg() != 0 || strings.TrimSpace(*outputPath) == "" || (*format != "text" && *format != "json") {
_, _ = fmt.Fprintln(stderr, "agentic-go source-view: --output is required; --format must be text or json")
return 2
}
if invalidCLIArgument(*branch) || invalidCLIArgument(*workspacePath) {
_, _ = fmt.Fprintln(stderr, "agentic-go source-view: branch and workspace must each be one local argument")
return 2
}

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
defer cancel()
ws, err := workspace.Open(ctx, *workspacePath)
if err != nil {
_, _ = fmt.Fprintf(stderr, "agentic-go source-view: validating workspace: %v\n", err)
return 1
}
runner, err := execution.New(ws, execution.Config{MaxConcurrent: 2, Timeout: 5 * time.Minute})
if err != nil {
_, _ = fmt.Fprintf(stderr, "agentic-go source-view: creating process runner: %v\n", err)
return 1
}
result, err := sourceview.Create(ctx, runner, ws, sourceview.Request{
Branch: *branch, OutputPath: *outputPath, IncludeDirty: *includeDirty,
})
if err != nil {
_, _ = fmt.Fprintf(stderr, "agentic-go source-view: %v\n", err)
return 1
}
if err := writeSourceViewResult(stdout, *format, result); err != nil {
_, _ = fmt.Fprintf(stderr, "agentic-go source-view: writing result: %v\n", err)
return 1
}
return 0
}

func writeSourceViewResult(writer io.Writer, format string, result sourceview.Result) error {
switch format {
case "json":
return json.NewEncoder(writer).Encode(result)
case "text":
coverage := "complete Git tree checkout"
if !result.CheckoutComplete {
coverage = "partial Git tree checkout"
}
if _, err := fmt.Fprintf(writer, "Branch view: %s\nCommit: %s\nTree: %s\nPath: %s\nDirty overlay: %t\nCheckout: %s\n", result.Ref, result.Commit, result.Tree, result.ViewPath, result.OverlayIncluded, coverage); err != nil {
return err
}
for _, limitation := range result.CheckoutLimitations {
if _, err := fmt.Fprintf(writer, "Checkout limitation: %s\n", limitation); err != nil {
return err
}
}
return nil
default:
return fmt.Errorf("unsupported output format %q", format)
}
}
Loading
Loading