Skip to content

Add opt-in shell-free Go repository profile for Copilot SDK - #62776

Closed
pelikhan with Copilot wants to merge 17 commits into
mainfrom
copilot/add-opt-in-shell-free-profile
Closed

pelikhan with Copilot wants to merge 17 commits into
mainfrom
copilot/add-opt-in-shell-free-profile

Conversation

Copilot AI commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Copilot SDK workflows lacked a closed native repository lifecycle when shell and task tools were disabled. This adds an opt-in tools.profile: go runtime that supports constrained repository inspection, editing, validation, and publication without arbitrary process access.

  • Profile contract

    • Adds tools.profile: go (including merged imported profiles).
    • Keeps default tool behavior unchanged.
    • Disables shell, generic task tools, and CLI proxy for profiled SDK sessions.
  • Native repository runtime

    • Exposes only status, diff, prepare_branch, format, readiness, validate, and commit.
    • Rejects arbitrary executables, arguments, working directories, and environment overrides.
    • Uses credential-free, bounded Git and Go subprocesses.
  • Publication safeguards

    • Anchors projection to GITHUB_SHA.
    • Rejects tracked, untracked, ignored, and validation-created mutations from publication.
    • Requires current successful validation of the eligible projected bytes before commit.
  • MCP, packaging, and diagnostics

    • Locks the native/MCP tool catalog and stages profile-specific MCP configuration privately.
    • Packages transitive safe-output helpers, including branch_pattern_helpers.cjs.
    • Returns redacted, bounded native failure objects with operation and output context.
    • Preserves legacy MCP servers named profile when imported.
  • Coverage and documentation

    • Adds promptless direct and gateway-backed repository-profile integration coverage.
    • Documents the profile and its constraints in engine, tool, safe-output, and SDK-driver references.
tools:
  profile: go

engine:
  id: copilot
  copilot-sdk: true

sandbox:
  agent: awf

Copilot AI and others added 7 commits September 23, 2026 00:12
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…rors

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Resolve ambient module-cache discovery, keep native MCP profile-only, and validate merged tools.profile values.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add opt-in shell-free native repository profile for Copilot SDK workflows Add opt-in shell-free Go repository profile for Copilot SDK Sep 23, 2026
Copilot AI requested a review from pelikhan September 23, 2026 00:30
@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot make feature experimental
update compiler security spec

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot apply to existing go centric agentic workflows like "pure loc

Copilot AI and others added 2 commits September 23, 2026 00:57
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot make feature experimental
update compiler security spec

Addressed in 45f7d63: tools.profile: go now emits an experimental compiler warning, its documentation identifies it as experimental, and the security architecture specification defines its closed compiler contract.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot apply to existing go centric agentic workflows like "pure loc

Applied to PureLock in d5b1181, with native repository operation and artifact guidance clarified in 2d183c1.

}
await preparation;
}
const gitArguments = ["--no-pager", "-c", `core.hooksPath=${hooks}`, "-c", "core.fsmonitor=false", "-c", "core.untrackedCache=false", "-c", "commit.gpgSign=false", "-c", "protocol.allow=never"];
@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot investigate implementing the profile as a shared agentic workflow (without profile keyword). Identify missing features

@github-actions

This comment has been minimized.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot split and add extensive testing. Consider other profile for typescript, python

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot split and add extensive testing. Consider other profile for typescript, python

Split done in 8a1e9a2: extracted the Go-specific gofmt/go vet/go build/go test argv builders from copilot_sdk_repo_tools.cjs into a new, dependency-free copilot_sdk_repo_go_toolchain.cjs module, with 16 new unit tests covering argv construction and edge cases (empty file lists, multiple files, full vs. quick test mode, immutability). All 377 existing repo-profile tests still pass unchanged. This isolates the fixed command contract from the SDK tool-call dispatch, matching the boundary described earlier: copilot_sdk_repo_process/workspace/policy/projection/diagnostics.cjs stay generic, copilot_sdk_repo_tools.cjs stays the SDK-specific adapter, and now the Go command argv itself is its own reviewable unit.

On typescript/python: investigated and found a hard architectural blocker, not just missing effort. findRepositoryExecutable (workspace.cjs:97-116) requires every resolved binary to live outside the repository checkout (isWithin(root, resolved) throws "Repository-owned executables are not permitted"). Go's toolchain (go, gofmt) is normally a global, system-installed binary, so this holds. TypeScript's toolchain (tsc, prettier, eslint) and most Python lint/format tools (black, mypy, ruff) are near-universally installed as repo-local devDependencies/.venv binaries, not global executables — exactly the case this check is designed to reject. Supporting them for real would mean either:

  1. Weakening the repo-owned-executable rejection (a deliberate security boundary, not an oversight), or
  2. Requiring those tools to be globally pre-installed on the runner outside the checkout, which doesn't match how virtually every TS/Python project pins its toolchain versions today.

Given that trade-off touches the core security guarantee of the profile, I'm not making that change without a dedicated design/security review, so I haven't added typescript/python profile values in this PR. Happy to scope that as a follow-up once there's agreement on how (or whether) to admit repo-local toolchain binaries.

Comment on lines +40 to +42
github:
mode: local
min-integrity: none
@github-actions

Copy link
Copy Markdown
Contributor

Hey @Copilot 👋 — thanks for implementing the opt-in shell-free Go repository profile for Copilot SDK! This is a significant contribution that addresses #61629 by adding a closed native repository lifecycle with constrained repository inspection, editing, validation, and publication.

✅ This PR looks great and ready for review! It includes:

  • Comprehensive integration test coverage (20 test files modified)
  • Clear documentation of the profile contract and constraints across reference docs
  • Structured publication safeguards, credential-free operations, and bounded failure diagnostics
  • Proper packaging of transitive runtime helpers and MCP configuration

The 122-file change set is well-motivated by the scope of the feature—adding a complete new tool profile requires coordination across the compiler, runtime, documentation, safe-outputs, and test layers. The diff is focused and cohesive.

Warning

Firewall blocked 2 domains

The following domains were blocked by the firewall during workflow execution:

  • github.com
  • o205451.ingest.us.sentry.io

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"
    - "o205451.ingest.us.sentry.io"

See Network Configuration for more information.

Generated by ✅ Contribution Check · copilot · auto · 63.8 AIC · ⌖ 7.02 AIC · ⊞ 9.2K · ◷

Comment on lines +1087 to +1106
if [ -z "${RUNNER_TEMP:-}" ]; then
echo "RUNNER_TEMP is required to stage Copilot SDK MCP config" >&2
exit 1
fi
if ! (umask 077 && mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config"); then
echo "Failed to create Copilot SDK MCP config directory" >&2
exit 1
fi
if ! chmod 700 "${RUNNER_TEMP}/gh-aw/mcp-config"; then
echo "Failed to secure Copilot SDK MCP config directory" >&2
exit 1
fi
if ! (umask 077 && cp "$HOME/.copilot/mcp-config.json" "${RUNNER_TEMP}/gh-aw/mcp-config/copilot-sdk.json"); then
echo "Failed to stage Copilot SDK MCP config" >&2
exit 1
fi
if ! chmod 600 "${RUNNER_TEMP}/gh-aw/mcp-config/copilot-sdk.json"; then
echo "Failed to secure Copilot SDK MCP config" >&2
exit 1
fi

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot refactor into actions/setup/sh shell script

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored in 6ffe4b8: the staging block now lives in actions/setup/sh/stage_copilot_sdk_mcp_config.sh (installed to ${RUNNER_TEMP}/gh-aw/actions/ by actions/setup/setup.sh, same as the other sh/*.sh scripts). The generated step is reduced to a RUNNER_TEMP guard, bash "${RUNNER_TEMP}/gh-aw/actions/stage_copilot_sdk_mcp_config.sh" || exit 1, and the GH_AW_MCP_CONFIG export; the fail-closed test matrix now executes the shipped script.

}

/** @param {string[]} inputs @param {string[]} supplied */
function diagnosticMasks(inputs, supplied) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot reuse existing redaction functions

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 9dfa2b2. diagnosticMasks no longer re-derives credential patterns: the Authorization-header, URL-userinfo, and query-parameter regexes moved into an exported CREDENTIAL_CONTEXT_PATTERNS in redact_secrets.cjs, alongside a new side-effect-free collectCredentialLiterals(content) that scans both those and BUILT_IN_PATTERNS. Diagnostics now calls that helper (plus the already-shared collectAddMaskedValues/applyAddMaskRedaction), so diagnostic, artifact, and step-summary redaction share one source of truth.

redactBuiltInPatterns itself isn't callable here — it logs via the core global, which isn't installed in the SDK driver process — hence the core-free collector rather than a direct call. Added 9 unit tests for the new helper; all 191 repo-profile and redaction tests pass.

Copilot AI and others added 2 commits September 23, 2026 10:33
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot investigate supporting the go profile in non-copilot-sdk like copilot/claude/codex/pi engines

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot investigate supporting the go profile in non-copilot-sdk like copilot/claude/codex/pi engines

Investigated. Nothing blocks this in principle — the blocker is tool delivery, not the runtime — but it needs a new engine-neutral server plus a per-engine compiler gate. Findings:

1. Tool delivery (the main missing piece). Non-SDK engines can only receive custom tools over MCP; defineTool exists only in the SDK driver. Two hosting shapes are already precedented in this repo:

  • containerized stdio through the gateway — validateSharedMCPConfig (pkg/workflow/mcp_config_custom.go:124-136) rejects any non-docker stdio command, so this needs an image with the Go toolchain and an rw mounts entry for the checkout;
  • a host-side server reached over HTTP, like mcp-scripts and the safe-outputs server (actions/setup/setup.sh:416), which runs next to the checkout with no mount/toolchain packaging problem.

Missing work either way: a go_repository MCP entry point + tool schema, its setup.sh install, and per-engine config staging (claude .mcp.json, codex TOML, copilot mcp-config.json, pi). The runtime itself is reusable as-is — copilot_sdk_repo_process/workspace/policy/projection/diagnostics/go_toolchain.cjs contain no SDK imports; only copilot_sdk_repo_tools.cjs needs an MCP sibling, plus a small adapter turning the current ToolResultObject failure envelopes into MCP isError content blocks.

2. Shell-free enforcement is available on every engine, through different knobs. copilot/claude/gemini via BashCommandAllowlist, codex via features.shell_tool=false (EngineCapabilities.BashDisable, pkg/workflow/codex_engine.go:68), pi via the Copilot CLI. So the bash: false half of the contract is portable. What is not portable today is the gate itself: validateCopilotToolProfile (pkg/workflow/copilot_engine_tool_profile.go:73) hardcodes EngineConfig.ID == "copilot" + isCopilotSDKMode, and derives permissions via computeCopilotToolArguments/buildCopilotSDKToolConfigJSON. That would become an EngineCapabilities flag plus per-engine assertions that cli-proxy, mcp-scripts run: bodies, and github.mode: gh-proxy stay off.

3. Closed tool catalog weakens outside the SDK. The SDK locks the native+MCP catalog in-process. Elsewhere the equivalent is engine allow-list flags plus the gateway's per-server tools: filter — sufficient for MCP tools, but each engine's built-in read/write/edit tools are only individually deniable where the engine exposes a deny list (claude does; codex/gemini do not enumerate them). So the profile's "fixed action surface" guarantee is strongest on copilot/claude.

4. Session state and cancellation port cleanly. The validate→commit fingerprint is per-session state; an MCP server process is per-run, so it survives, and a restarted server fails closed (re-validation required). copilot_sdk_repo_process.cjs already enforces bounded timeouts and output caps, so losing the SDK AbortController is not a correctness issue.

5. Policy binding and path parity are the remaining unknowns. The compile-time projection (projectGoRepositoryPolicy + expression validation) currently emits the SDK tool-config JSON; for a server it becomes an engine-neutral policy file passed via server env: (no credentials involved). A host-side server must also be validated against the gateway's host-path remapping under docker-sbx/gvisor, so paths the agent reports match those the server mutates.

Recommendation: keep this PR SDK-only, and scope a follow-up that (a) lifts go_repository into an engine-neutral MCP server reusing the six generic modules unchanged, and (b) replaces the copilot-only gate with a capability check plus per-engine hardening assertions — starting with copilot CLI and claude, where the deny-list surface is strongest, then codex and pi.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot break down this implementation in su feature / front matter field that could be used to reassemble the feature as a shared agentic workflow

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan pelikhan closed this Sep 23, 2026

Copilot AI commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot break down this implementation in su feature / front matter field that could be used to reassemble the feature as a shared agentic workflow

Implemented in 7e12f86 and 2c80db6. tools.repository: go is now a composable frontmatter sub-feature, with shared/go-repository.md; PureLock imports it. The compiler preserves the closed Go runtime and validates the combined workflow. Importers still explicitly declare bash: false and cli-proxy: false, because strict validation requires those denials in the importing workflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add an opt-in shell-free native repository profile for Copilot SDK workflows

4 participants