Skip to content

refactor: installer core clean architecture refactor - #288

Merged
777genius merged 28 commits into
mainfrom
refactor/installer-core-clean-architecture
Sep 19, 2026
Merged

777genius merged 28 commits into
mainfrom
refactor/installer-core-clean-architecture

Conversation

@777genius

@777genius 777genius commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Summary

Tracking PR for bringing the installer core (install/integrationctl/agentplugins, cli/plugin-kit-ai/internal/agentpluginscli, cli/plugin-kit-ai/cmd/agentplugins) up to parity with other project on SOLID, DRY, Clean Architecture, modularity, and code quality. An independent audit scored our core 5.8/10 against their 7.4/10 on these criteria.

This is a work-in-progress base branch. Individual parts land here as separate PRs (lint gate, ports/DIP, client adapter contract, per-client migration, CI guardrails, etc). This PR itself will not be merged into main until the whole refactor is done and explicitly approved.

Full plan (target architecture, part-by-part breakdown, lint gate config, CI mechanics, adversarial review results): docs/plans/installer-core-clean-architecture-plan.md.

Test plan

  • Each part lands with its own PR into this branch, gated by a fast CI check (lint + core tests + cross-build + vet)
  • Full required CI runs on this branch after each merge (async, non-blocking)
  • Behavior-preserving guarantees verified via golden tests before touching client-specific dispatch code
  • Final merge into main only on explicit approval

…r core

Full plan for bringing the agentplugins/agentpluginscli/cmd core up to
parity with AgentBridge on SOLID/DRY/Clean Architecture/modularity/code
quality (independent audit: 5.8/10 vs 7.4/10). Reviewed adversarially
against the actual code before landing; six mandatory fixes applied.
@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 434 files, which is 334 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

Usage-priced reviews support at most 300 files.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 7704c164-4b66-4fd5-aaa3-8ee19f8d51b2

📥 Commits

Reviewing files that changed from the base of the PR and between b443eb7 and 9e4a86e.

⛔ Files ignored due to path filters (4)
  • cli/plugin-kit-ai/go.sum is excluded by !**/*.sum
  • go.work is excluded by !**/*.work
  • install/integrationctl/agentplugins/go.sum is excluded by !**/*.sum
  • install/integrationctl/go.sum is excluded by !**/*.sum
📒 Files selected for processing (434)
  • .github/pull_request_template.md
  • .github/workflows/agentplugins-release.yml
  • .github/workflows/authoring-milestone-a-e2e.yml
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/core-fast.yml
  • .github/workflows/coverage.yml
  • .github/workflows/govulncheck.yml
  • .github/workflows/lint.yml
  • .github/workflows/polyglot-smoke.yml
  • .golangci.yml
  • CONTRIBUTING.md
  • Makefile
  • cli/plugin-kit-ai/cmd/agentplugins/bootstrapgen/main.go
  • cli/plugin-kit-ai/cmd/agentplugins/compose.go
  • cli/plugin-kit-ai/cmd/agentplugins/main.go
  • cli/plugin-kit-ai/cmd/agentplugins/release_root.go
  • cli/plugin-kit-ai/cmd/agentplugins/release_workflow_test.go
  • cli/plugin-kit-ai/cmd/plugin-kit-ai/main.go
  • cli/plugin-kit-ai/cmd/plugin-kit-ai/publication_doctor_run.go
  • cli/plugin-kit-ai/go.mod
  • cli/plugin-kit-ai/internal/agentpluginscli/add.go
  • cli/plugin-kit-ai/internal/agentpluginscli/add_dry_run_golden_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/add_multi.go
  • cli/plugin-kit-ai/internal/agentpluginscli/add_normalize_target_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/add_result.go
  • cli/plugin-kit-ai/internal/agentpluginscli/add_targets.go
  • cli/plugin-kit-ai/internal/agentpluginscli/app.go
  • cli/plugin-kit-ai/internal/agentpluginscli/binding.go
  • cli/plugin-kit-ai/internal/agentpluginscli/chatgpt_prepare_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/cli_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/client_policy.go
  • cli/plugin-kit-ai/internal/agentpluginscli/client_registry_injection_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/directory_rollout_semantics_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/engine_boundary.go
  • cli/plugin-kit-ai/internal/agentpluginscli/engine_switch.go
  • cli/plugin-kit-ai/internal/agentpluginscli/idempotent_update_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/interactive_directory.go
  • cli/plugin-kit-ai/internal/agentpluginscli/interactive_loaded.go
  • cli/plugin-kit-ai/internal/agentpluginscli/interactive_targets.go
  • cli/plugin-kit-ai/internal/agentpluginscli/kiro_prepare_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/lifecycle.go
  • cli/plugin-kit-ai/internal/agentpluginscli/lifecycle_semantics_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/opencode_runtime_notice.go
  • cli/plugin-kit-ai/internal/agentpluginscli/outdated.go
  • cli/plugin-kit-ai/internal/agentpluginscli/preflight.go
  • cli/plugin-kit-ai/internal/agentpluginscli/prepare.go
  • cli/plugin-kit-ai/internal/agentpluginscli/read.go
  • cli/plugin-kit-ai/internal/agentpluginscli/read_native_projection_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/read_reconciliation.go
  • cli/plugin-kit-ai/internal/agentpluginscli/read_reconciliation_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/remove_multi.go
  • cli/plugin-kit-ai/internal/agentpluginscli/repair_multi.go
  • cli/plugin-kit-ai/internal/agentpluginscli/review_regression_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/source.go
  • cli/plugin-kit-ai/internal/agentpluginscli/state_migration.go
  • cli/plugin-kit-ai/internal/agentpluginscli/target_eligibility_guidance_test.go
  • cli/plugin-kit-ai/internal/agentpluginscli/testdata/golden/chatgpt_official_app.json
  • cli/plugin-kit-ai/internal/agentpluginscli/testdata/golden/codex_and_cursor_remote_mcp.json
  • cli/plugin-kit-ai/internal/agentpluginscli/testdata/golden/cursor_manifest_only.json
  • cli/plugin-kit-ai/internal/agentpluginscli/update_all.go
  • cli/plugin-kit-ai/internal/agentpluginscli/update_multi.go
  • cli/plugin-kit-ai/internal/authoring/commands/commands.go
  • cli/plugin-kit-ai/internal/authoring/commands/dev_session_test.go
  • cli/plugin-kit-ai/internal/authoring/commands/installer_test.go
  • cli/plugin-kit-ai/internal/authoring/commands/packed_installer_test.go
  • cli/plugin-kit-ai/internal/authoring/commands/public_contract_test.go
  • cli/plugin-kit-ai/internal/authoring/commands/readiness_review_probe_test.go
  • cli/plugin-kit-ai/internal/authoring/commands/readiness_test.go
  • cli/plugin-kit-ai/internal/authoring/commands/skills_test.go
  • cli/plugin-kit-ai/internal/authoring/commands/slice_test.go
  • cli/plugin-kit-ai/internal/authoring/commands/vertical_fix_test.go
  • cli/plugin-kit-ai/internal/authoring/readiness/readiness.go
  • cli/plugin-kit-ai/internal/authoring/readiness/readiness_test.go
  • cli/plugin-kit-ai/internal/authoring/scaffold/apply_test.go
  • cli/plugin-kit-ai/internal/authoringcli/boundary_test.go
  • cli/plugin-kit-ai/internal/authoringcli/facts_boundary_test.go
  • cli/plugin-kit-ai/internal/platformexec/codex_import.go
  • cli/plugin-kit-ai/internal/platformexec/gemini_generate_render_outputs.go
  • cli/plugin-kit-ai/internal/platformexec/opencode_validate_agents.go
  • cli/plugin-kit-ai/internal/pluginmodel/mcp_render.go
  • cli/plugin-kit-ai/tools/authoring-docs/source.go
  • docs/ARCHITECTURE.md
  • docs/adr/0007-client-adapter-contract-and-registry.md
  • docs/plans/installer-core-clean-architecture-plan.md
  • docs/plans/installer-core-part-12-contract-module.md
  • install/integrationctl/adapters/evidence/registry.go
  • install/integrationctl/adapters/pathpolicy/policy.go
  • install/integrationctl/agentplugins/adapters/catalog/catalog.go
  • install/integrationctl/agentplugins/adapters/clientdetect/detector.go
  • install/integrationctl/agentplugins/adapters/clientdetect/detector_test.go
  • install/integrationctl/agentplugins/adapters/clientdetect/golden_test.go
  • install/integrationctl/agentplugins/adapters/clientdetect/host.go
  • install/integrationctl/agentplugins/adapters/clientdetect/testdata/golden/detect_darwin.json
  • install/integrationctl/agentplugins/adapters/clientdetect/testdata/golden/detect_linux.json
  • install/integrationctl/agentplugins/adapters/clientdetect/testdata/golden/detect_windows.json
  • install/integrationctl/agentplugins/adapters/clientdetect/version.go
  • install/integrationctl/agentplugins/adapters/directoryv1/validate.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/cline_cwd_test.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/document.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/io.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/kernel.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/kernel_test.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/lock.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/lock_test.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/lock_unix.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/lock_windows.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/open_nofollow_unix.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/open_nofollow_windows.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/opencode_exact_keys_test.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/project.go
  • install/integrationctl/agentplugins/adapters/nativeconfig/types.go
  • install/integrationctl/agentplugins/adapters/packageview/source_unsupported.go
  • install/integrationctl/agentplugins/adapters/packageview/source_windows_test.go
  • install/integrationctl/agentplugins/clients/all/registry.go
  • install/integrationctl/agentplugins/clients/all/registry_test.go
  • install/integrationctl/agentplugins/clients/chatgpt/detect.go
  • install/integrationctl/agentplugins/clients/chatgpt/identity.go
  • install/integrationctl/agentplugins/clients/chatgpt/lifecycle.go
  • install/integrationctl/agentplugins/clients/chatgpt/plan.go
  • install/integrationctl/agentplugins/clients/chatgpt/project.go
  • install/integrationctl/agentplugins/clients/claude/claude.go
  • install/integrationctl/agentplugins/clients/claude/detect.go
  • install/integrationctl/agentplugins/clients/claude/identity.go
  • install/integrationctl/agentplugins/clients/claude/lifecycle.go
  • install/integrationctl/agentplugins/clients/claude/list.go
  • install/integrationctl/agentplugins/clients/claude/plan.go
  • install/integrationctl/agentplugins/clients/claude/probe.go
  • install/integrationctl/agentplugins/clients/claude/project.go
  • install/integrationctl/agentplugins/clients/clients.go
  • install/integrationctl/agentplugins/clients/cline/activate.go
  • install/integrationctl/agentplugins/clients/cline/detect.go
  • install/integrationctl/agentplugins/clients/cline/identity.go
  • install/integrationctl/agentplugins/clients/cline/lifecycle.go
  • install/integrationctl/agentplugins/clients/cline/lifecycle_mcp.go
  • install/integrationctl/agentplugins/clients/cline/lifecycle_skills.go
  • install/integrationctl/agentplugins/clients/cline/native.go
  • install/integrationctl/agentplugins/clients/cline/native_project.go
  • install/integrationctl/agentplugins/clients/cline/plan.go
  • install/integrationctl/agentplugins/clients/cline/project.go
  • install/integrationctl/agentplugins/clients/codex/detect.go
  • install/integrationctl/agentplugins/clients/codex/identity.go
  • install/integrationctl/agentplugins/clients/codex/lifecycle.go
  • install/integrationctl/agentplugins/clients/codex/lifecycle_deactivate.go
  • install/integrationctl/agentplugins/clients/codex/list.go
  • install/integrationctl/agentplugins/clients/codex/marketplace_cleanup.go
  • install/integrationctl/agentplugins/clients/codex/plan.go
  • install/integrationctl/agentplugins/clients/codex/project.go
  • install/integrationctl/agentplugins/clients/contracttest/README.md
  • install/integrationctl/agentplugins/clients/contracttest/contracttest.go
  • install/integrationctl/agentplugins/clients/contracttest/contracttest_test.go
  • install/integrationctl/agentplugins/clients/contracttest/hostdetector.go
  • install/integrationctl/agentplugins/clients/contracttest/hostdetector_test.go
  • install/integrationctl/agentplugins/clients/contracttest/identity.go
  • install/integrationctl/agentplugins/clients/contracttest/identity_test.go
  • install/integrationctl/agentplugins/clients/contracttest/lifecycle.go
  • install/integrationctl/agentplugins/clients/contracttest/lifecycle_test.go
  • install/integrationctl/agentplugins/clients/contracttest/parity.go
  • install/integrationctl/agentplugins/clients/contracttest/planrefiner.go
  • install/integrationctl/agentplugins/clients/contracttest/projector.go
  • install/integrationctl/agentplugins/clients/contracttest/projector_test.go
  • install/integrationctl/agentplugins/clients/copilot/detect.go
  • install/integrationctl/agentplugins/clients/copilot/identity.go
  • install/integrationctl/agentplugins/clients/copilot/lifecycle.go
  • install/integrationctl/agentplugins/clients/copilot/plan.go
  • install/integrationctl/agentplugins/clients/copilot/project.go
  • install/integrationctl/agentplugins/clients/cursor/detect.go
  • install/integrationctl/agentplugins/clients/cursor/identity.go
  • install/integrationctl/agentplugins/clients/cursor/lifecycle.go
  • install/integrationctl/agentplugins/clients/cursor/plan.go
  • install/integrationctl/agentplugins/clients/cursor/project.go
  • install/integrationctl/agentplugins/clients/detection.go
  • install/integrationctl/agentplugins/clients/gemini/activate.go
  • install/integrationctl/agentplugins/clients/gemini/detect.go
  • install/integrationctl/agentplugins/clients/gemini/identity.go
  • install/integrationctl/agentplugins/clients/gemini/native.go
  • install/integrationctl/agentplugins/clients/gemini/native_apply.go
  • install/integrationctl/agentplugins/clients/gemini/native_mcp.go
  • install/integrationctl/agentplugins/clients/gemini/native_objects.go
  • install/integrationctl/agentplugins/clients/gemini/native_server.go
  • install/integrationctl/agentplugins/clients/gemini/native_skills.go
  • install/integrationctl/agentplugins/clients/gemini/plan.go
  • install/integrationctl/agentplugins/clients/gemini/project.go
  • install/integrationctl/agentplugins/clients/host.go
  • install/integrationctl/agentplugins/clients/identity.go
  • install/integrationctl/agentplugins/clients/internal/exampleclient/exampleclient.go
  • install/integrationctl/agentplugins/clients/internal/exampleclient/exampleclient_test.go
  • install/integrationctl/agentplugins/clients/kiro/acp.go
  • install/integrationctl/agentplugins/clients/kiro/acp_codec.go
  • install/integrationctl/agentplugins/clients/kiro/acp_status.go
  • install/integrationctl/agentplugins/clients/kiro/acp_test.go
  • install/integrationctl/agentplugins/clients/kiro/activate.go
  • install/integrationctl/agentplugins/clients/kiro/detect.go
  • install/integrationctl/agentplugins/clients/kiro/errors.go
  • install/integrationctl/agentplugins/clients/kiro/helpers_test.go
  • install/integrationctl/agentplugins/clients/kiro/identity.go
  • install/integrationctl/agentplugins/clients/kiro/lifecycle.go
  • install/integrationctl/agentplugins/clients/kiro/mcp.go
  • install/integrationctl/agentplugins/clients/kiro/native_test.go
  • install/integrationctl/agentplugins/clients/kiro/pipe_bytes_darwin.go
  • install/integrationctl/agentplugins/clients/kiro/pipe_bytes_linux.go
  • install/integrationctl/agentplugins/clients/kiro/pipe_fallback.go
  • install/integrationctl/agentplugins/clients/kiro/pipe_unix.go
  • install/integrationctl/agentplugins/clients/kiro/pipe_windows.go
  • install/integrationctl/agentplugins/clients/kiro/plan.go
  • install/integrationctl/agentplugins/clients/kiro/project.go
  • install/integrationctl/agentplugins/clients/kiro/testdoubles_test.go
  • install/integrationctl/agentplugins/clients/lifecycle.go
  • install/integrationctl/agentplugins/clients/opencode/activate.go
  • install/integrationctl/agentplugins/clients/opencode/detect.go
  • install/integrationctl/agentplugins/clients/opencode/identity.go
  • install/integrationctl/agentplugins/clients/opencode/native.go
  • install/integrationctl/agentplugins/clients/opencode/native_apply.go
  • install/integrationctl/agentplugins/clients/opencode/native_mcp.go
  • install/integrationctl/agentplugins/clients/opencode/native_project.go
  • install/integrationctl/agentplugins/clients/opencode/native_skills.go
  • install/integrationctl/agentplugins/clients/opencode/plan.go
  • install/integrationctl/agentplugins/clients/opencode/project.go
  • install/integrationctl/agentplugins/clients/planning.go
  • install/integrationctl/agentplugins/clients/registry.go
  • install/integrationctl/agentplugins/clients/registry_test.go
  • install/integrationctl/agentplugins/clients/shared/activation.go
  • install/integrationctl/agentplugins/clients/shared/capacity.go
  • install/integrationctl/agentplugins/clients/shared/capacity_test.go
  • install/integrationctl/agentplugins/clients/shared/command.go
  • install/integrationctl/agentplugins/clients/shared/components.go
  • install/integrationctl/agentplugins/clients/shared/copilot_identity.go
  • install/integrationctl/agentplugins/clients/shared/copilot_identity_test.go
  • install/integrationctl/agentplugins/clients/shared/copilot_lifecycle.go
  • install/integrationctl/agentplugins/clients/shared/copilot_status.go
  • install/integrationctl/agentplugins/clients/shared/detection.go
  • install/integrationctl/agentplugins/clients/shared/diagnostic.go
  • install/integrationctl/agentplugins/clients/shared/digest.go
  • install/integrationctl/agentplugins/clients/shared/identity.go
  • install/integrationctl/agentplugins/clients/shared/json.go
  • install/integrationctl/agentplugins/clients/shared/layout.go
  • install/integrationctl/agentplugins/clients/shared/manifest.go
  • install/integrationctl/agentplugins/clients/shared/marketplace.go
  • install/integrationctl/agentplugins/clients/shared/marketplace_project.go
  • install/integrationctl/agentplugins/clients/shared/mcp_projection.go
  • install/integrationctl/agentplugins/clients/shared/native_lifecycle.go
  • install/integrationctl/agentplugins/clients/shared/native_registry.go
  • install/integrationctl/agentplugins/clients/shared/objects.go
  • install/integrationctl/agentplugins/clients/shared/openai_project.go
  • install/integrationctl/agentplugins/clients/shared/plan.go
  • install/integrationctl/agentplugins/clients/shared/rename_exclusive_darwin.go
  • install/integrationctl/agentplugins/clients/shared/rename_exclusive_fallback.go
  • install/integrationctl/agentplugins/clients/shared/rename_exclusive_linux_amd64.go
  • install/integrationctl/agentplugins/clients/shared/rename_exclusive_linux_arm64.go
  • install/integrationctl/agentplugins/clients/shared/stdio.go
  • install/integrationctl/agentplugins/clients/shared/stdio_paths_test.go
  • install/integrationctl/agentplugins/clients/staging.go
  • install/integrationctl/agentplugins/clients/vscode/detect.go
  • install/integrationctl/agentplugins/clients/vscode/identity.go
  • install/integrationctl/agentplugins/clients/vscode/lifecycle.go
  • install/integrationctl/agentplugins/clients/vscode/plan.go
  • install/integrationctl/agentplugins/clients/vscode/project.go
  • install/integrationctl/agentplugins/clients/windsurf/activate.go
  • install/integrationctl/agentplugins/clients/windsurf/detect.go
  • install/integrationctl/agentplugins/clients/windsurf/identity.go
  • install/integrationctl/agentplugins/clients/windsurf/lifecycle.go
  • install/integrationctl/agentplugins/clients/windsurf/native.go
  • install/integrationctl/agentplugins/clients/windsurf/native_project.go
  • install/integrationctl/agentplugins/clients/windsurf/native_server.go
  • install/integrationctl/agentplugins/clients/windsurf/plan.go
  • install/integrationctl/agentplugins/clients/windsurf/project.go
  • install/integrationctl/agentplugins/domain/clients.go
  • install/integrationctl/agentplugins/domain/clients_test.go
  • install/integrationctl/agentplugins/domain/directory.go
  • install/integrationctl/agentplugins/domain/directory_context7_preparation.go
  • install/integrationctl/agentplugins/domain/install_intent.go
  • install/integrationctl/agentplugins/domain/planning.go
  • install/integrationctl/agentplugins/domain/security.go
  • install/integrationctl/agentplugins/domain/traits.go
  • install/integrationctl/agentplugins/domain/traits_test.go
  • install/integrationctl/agentplugins/go.mod
  • install/integrationctl/agentplugins/internal/archtest/archtest.go
  • install/integrationctl/agentplugins/internal/archtest/boundaries_test.go
  • install/integrationctl/agentplugins/internal/archtest/budget_test.go
  • install/integrationctl/agentplugins/internal/archtest/contract_edges_test.go
  • install/integrationctl/agentplugins/internal/archtest/main.go
  • install/integrationctl/agentplugins/internal/archtest/pathpolicy.go
  • install/integrationctl/agentplugins/internal/archtest/pathpolicy_test.go
  • install/integrationctl/agentplugins/internal/archtest/testdata/client_id_budget.json
  • install/integrationctl/agentplugins/internal/goldentest/goldentest.go
  • install/integrationctl/agentplugins/planner/client_rules_test.go
  • install/integrationctl/agentplugins/planner/codex_transport_test.go
  • install/integrationctl/agentplugins/planner/compatibility.go
  • install/integrationctl/agentplugins/planner/compatibility_test.go
  • install/integrationctl/agentplugins/planner/facade_actions_test.go
  • install/integrationctl/agentplugins/planner/golden_test.go
  • install/integrationctl/agentplugins/planner/intent.go
  • install/integrationctl/agentplugins/planner/intent_test.go
  • install/integrationctl/agentplugins/planner/manual_preparation_test.go
  • install/integrationctl/agentplugins/planner/path_policy_test.go
  • install/integrationctl/agentplugins/planner/planner.go
  • install/integrationctl/agentplugins/planner/planner_support_test.go
  • install/integrationctl/agentplugins/planner/planner_test.go
  • install/integrationctl/agentplugins/planner/registry_test.go
  • install/integrationctl/agentplugins/planner/testdata/golden/compat_invalid_components.json
  • install/integrationctl/agentplugins/planner/testdata/golden/compat_remote_mcp_and_app.json
  • install/integrationctl/agentplugins/planner/testdata/golden/compat_skills_only.json
  • install/integrationctl/agentplugins/planner/testdata/golden/compat_stdio_mcp.json
  • install/integrationctl/agentplugins/planner/testdata/golden/plan_detected_divergence.json
  • install/integrationctl/agentplugins/planner/testdata/golden/plan_invalid_components.json
  • install/integrationctl/agentplugins/planner/testdata/golden/plan_remote_mcp_and_app.json
  • install/integrationctl/agentplugins/planner/testdata/golden/plan_skills_only.json
  • install/integrationctl/agentplugins/planner/testdata/golden/plan_stdio_mcp.json
  • install/integrationctl/agentplugins/planner/windsurf_test.go
  • install/integrationctl/agentplugins/plannertest/plannertest.go
  • install/integrationctl/agentplugins/ports/contracttest/pathpolicy.go
  • install/integrationctl/agentplugins/ports/interfaces.go
  • install/integrationctl/agentplugins/ports/optional.go
  • install/integrationctl/agentplugins/ports/paths.go
  • install/integrationctl/agentplugins/ports/runner.go
  • install/integrationctl/agentplugins/providers/acp_fixtures_test.go
  • install/integrationctl/agentplugins/providers/activation_verifier.go
  • install/integrationctl/agentplugins/providers/activator.go
  • install/integrationctl/agentplugins/providers/activator_golden_test.go
  • install/integrationctl/agentplugins/providers/activator_registry_test.go
  • install/integrationctl/agentplugins/providers/activator_status_aliases_test.go
  • install/integrationctl/agentplugins/providers/activator_test.go
  • install/integrationctl/agentplugins/providers/capacity.go
  • install/integrationctl/agentplugins/providers/capacity_test.go
  • install/integrationctl/agentplugins/providers/chatgpt_prepare_test.go
  • install/integrationctl/agentplugins/providers/claude_launcher_test.go
  • install/integrationctl/agentplugins/providers/claude_lifecycle_test.go
  • install/integrationctl/agentplugins/providers/claude_path_topology_test.go
  • install/integrationctl/agentplugins/providers/claude_stdio_contract_test.go
  • install/integrationctl/agentplugins/providers/cline_native.go
  • install/integrationctl/agentplugins/providers/cline_native_test.go
  • install/integrationctl/agentplugins/providers/codex_marketplace_cleanup_test.go
  • install/integrationctl/agentplugins/providers/codex_marketplace_cleanup_windows_test.go
  • install/integrationctl/agentplugins/providers/codex_transport_test.go
  • install/integrationctl/agentplugins/providers/gemini_native.go
  • install/integrationctl/agentplugins/providers/gemini_native_test.go
  • install/integrationctl/agentplugins/providers/kiro_acp.go
  • install/integrationctl/agentplugins/providers/kiro_native.go
  • install/integrationctl/agentplugins/providers/managed_selection.go
  • install/integrationctl/agentplugins/providers/managed_selection_test.go
  • install/integrationctl/agentplugins/providers/managed_stdio.go
  • install/integrationctl/agentplugins/providers/native_identity.go
  • install/integrationctl/agentplugins/providers/native_identity_preparation_test.go
  • install/integrationctl/agentplugins/providers/native_identity_test.go
  • install/integrationctl/agentplugins/providers/native_identity_timeout_unix_test.go
  • install/integrationctl/agentplugins/providers/opencode_logical_keys_test.go
  • install/integrationctl/agentplugins/providers/opencode_native.go
  • install/integrationctl/agentplugins/providers/opencode_native_test.go
  • install/integrationctl/agentplugins/providers/opencode_transport_test.go
  • install/integrationctl/agentplugins/providers/optional_ports.go
  • install/integrationctl/agentplugins/providers/plugin_data_preflight.go
  • install/integrationctl/agentplugins/providers/portable_identity_test.go
  • install/integrationctl/agentplugins/providers/selected_environment_test.go
  • install/integrationctl/agentplugins/providers/stager.go
  • install/integrationctl/agentplugins/providers/stager_registry_test.go
  • install/integrationctl/agentplugins/providers/stager_sanitize.go
  • install/integrationctl/agentplugins/providers/stager_support_test.go
  • install/integrationctl/agentplugins/providers/stager_test.go
  • install/integrationctl/agentplugins/providers/staging_tree_test.go
  • install/integrationctl/agentplugins/providers/stdio_paths.go
  • install/integrationctl/agentplugins/providers/testdata/golden/activate.json
  • install/integrationctl/agentplugins/providers/testdata/golden/activate_client_responds.json
  • install/integrationctl/agentplugins/providers/testdata/golden/activate_client_responds_verify_only.json
  • install/integrationctl/agentplugins/providers/testdata/golden/activate_verify_only.json
  • install/integrationctl/agentplugins/providers/testdata/golden/deactivate_confirmed.json
  • install/integrationctl/agentplugins/providers/testdata/golden/deactivate_recorded_ownership.json
  • install/integrationctl/agentplugins/providers/testdata/golden/deactivate_unconfirmed.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/chatgpt.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/claude.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/cline.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/codex.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/copilot.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/cursor.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/gemini.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/kiro.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/opencode.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/vscode.json
  • install/integrationctl/agentplugins/providers/testdata/golden/staging/windsurf.json
  • install/integrationctl/agentplugins/providers/windsurf_launcher_test.go
  • install/integrationctl/agentplugins/providers/windsurf_native.go
  • install/integrationctl/agentplugins/providers/windsurf_native_test.go
  • install/integrationctl/agentplugins/providerstest/providerstest.go
  • install/integrationctl/agentplugins/usecase/apply.go
  • install/integrationctl/agentplugins/usecase/apply_commit.go
  • install/integrationctl/agentplugins/usecase/binding.go
  • install/integrationctl/agentplugins/usecase/claude_lifecycle_test.go
  • install/integrationctl/agentplugins/usecase/client_traits.go
  • install/integrationctl/agentplugins/usecase/codex_sse_lifecycle_test.go
  • install/integrationctl/agentplugins/usecase/component_readiness.go
  • install/integrationctl/agentplugins/usecase/component_readiness_test.go
  • install/integrationctl/agentplugins/usecase/delivery.go
  • install/integrationctl/agentplugins/usecase/group.go
  • install/integrationctl/agentplugins/usecase/group_activate.go
  • install/integrationctl/agentplugins/usecase/group_commit.go
  • install/integrationctl/agentplugins/usecase/group_plan.go
  • install/integrationctl/agentplugins/usecase/group_session.go
  • install/integrationctl/agentplugins/usecase/group_stage.go
  • install/integrationctl/agentplugins/usecase/group_test.go
  • install/integrationctl/agentplugins/usecase/identity.go
  • install/integrationctl/agentplugins/usecase/installation.go
  • install/integrationctl/agentplugins/usecase/intent.go
  • install/integrationctl/agentplugins/usecase/kiro_prepare_test.go
  • install/integrationctl/agentplugins/usecase/legacy_remove.go
  • install/integrationctl/agentplugins/usecase/legacy_remove_test.go
  • install/integrationctl/agentplugins/usecase/lifecycle.go
  • install/integrationctl/agentplugins/usecase/managed_selection.go
  • install/integrationctl/agentplugins/usecase/manual_remote_lifecycle_test.go
  • install/integrationctl/agentplugins/usecase/partial_selection_lifecycle_test.go
  • install/integrationctl/agentplugins/usecase/path_policy_dependency_test.go
  • install/integrationctl/agentplugins/usecase/path_semantics_integration_test.go
  • install/integrationctl/agentplugins/usecase/remove.go
  • install/integrationctl/agentplugins/usecase/remove_group.go
  • install/integrationctl/agentplugins/usecase/remove_group_native.go
  • install/integrationctl/agentplugins/usecase/remove_group_persist.go
  • install/integrationctl/agentplugins/usecase/remove_group_session.go
  • install/integrationctl/agentplugins/usecase/remove_prepare.go
  • install/integrationctl/agentplugins/usecase/remove_session.go
  • install/integrationctl/agentplugins/usecase/repair.go
  • install/integrationctl/agentplugins/usecase/repair_native.go
  • install/integrationctl/agentplugins/usecase/repair_package.go
  • install/integrationctl/agentplugins/usecase/repair_session.go
  • install/integrationctl/agentplugins/usecase/service.go
  • install/integrationctl/agentplugins/usecase/service_test.go
  • install/integrationctl/agentplugins/usecase/usecase_support_test.go
  • install/integrationctl/agentplugins/usecase/windsurf_lifecycle_test.go
  • install/integrationctl/agentplugins/usecasetest/usecasetest.go
  • install/integrationctl/go.mod
  • repotests/agentplugins_codex_native_e2e_test.go
  • repotests/agentplugins_native_fixture_test.go
  • repotests/agentplugins_opencode_native_e2e_test.go
  • repotests/agentplugins_release_contract_test.go
  • scripts/check-lint-baseline.sh
  • scripts/lint-baseline-renames.txt
  • website/tools/extractors/prepared-cli.mjs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 42.01971% with 3353 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.95%. Comparing base (b443eb7) to head (9e4a86e).

Files with missing lines Patch % Lines
...onctl/agentplugins/clients/cline/native_project.go 0.00% 154 Missing ⚠️
...tegrationctl/agentplugins/clients/gemini/native.go 0.00% 141 Missing ⚠️
...egrationctl/agentplugins/clients/codex/identity.go 0.00% 136 Missing ⚠️
...tegrationctl/agentplugins/clients/kiro/activate.go 0.00% 112 Missing ⚠️
...nstall/integrationctl/agentplugins/clients/host.go 0.00% 110 Missing ⚠️
...onctl/agentplugins/clients/gemini/native_server.go 0.00% 106 Missing ⚠️
...tegrationctl/agentplugins/clients/kiro/identity.go 28.87% 85 Missing and 16 partials ⚠️
...l/agentplugins/clients/contracttest/planrefiner.go 0.00% 92 Missing ⚠️
...ionctl/agentplugins/clients/cline/lifecycle_mcp.go 0.00% 90 Missing ⚠️
...ctl/agentplugins/clients/cline/lifecycle_skills.go 0.00% 89 Missing ⚠️
... and 90 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #288      +/-   ##
==========================================
- Coverage   64.23%   59.95%   -4.29%     
==========================================
  Files        1169     1321     +152     
  Lines       64109    67544    +3435     
==========================================
- Hits        41182    40494     -688     
- Misses      16949    21464    +4515     
+ Partials     5978     5586     -392     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

* ci: add golangci-lint size and architecture gate

Adds a single root .golangci.yml covering the three Go modules, wired into
Required as a parallel matrix job.

Two passes, because --new-from-* filters by changed line while funlen, gocyclo
and revive file-length-limit report on the declaration line: growing an old
function would otherwise slip through.

- changed lines: correctness and style, only-new-issues
- whole files: revive, funlen, gocyclo, gocognit, dupl, depguard

depguard locks the two layering rules that already hold today: domain imports
stdlib only, ports imports stdlib plus domain plus install/integrationctl/ports.
That last one is a deliberate exception, documented in docs/ARCHITECTURE.md:
Command and CommandResult are plain data types with no behavior, and duplicating
them into domain would create a second source of truth.

Files that already exceed the size limits are listed in a shrink-only legacy
baseline (163 size entries plus 14 pre-existing revive style entries, generated
by the first full run). scripts/check-lint-baseline.sh fails the build if the
block grows.

gocritic and gosec exclusions are picked from measured output, not guessed: six
gocritic checks account for 699 of 799 findings and six gosec rules for 266 of
273. revive unused-parameter is off, it fires 172 times on interface
implementations.

Also fixes the gofmt drift in the seven files that had it, and adds make
test-core, which runs the core suites with git hooks disabled so a user-level
commit hook cannot fail unrelated tests.

* ci: close the silent gaps in the lint gate

Review found the changed-lines pass was a no-op for the root module, and the
baseline was both too broad and too easy to widen.

The root matrix leg no longer passes working-directory. The action runs the PR
patch through path.relative(GITHUB_WORKSPACE, working-directory), which yields
"" for "."; every `diff --git` section then fails the ` a//` test and is
dropped, so --new-from-patch got an empty patch and the step passed on anything.
Reproduced with an unchecked os.Setenv in cmd/agentplugins-registry-mirror: the
unaltered patch reports errcheck, the rewritten one reports nothing.

uniq-by-line is off. gocognit and gocyclo both report on the declaration line
and only the first survived the default collapse, which hid 300 findings and
would have made the baseline look complete while exempting a file from gocognit
silently revealed its gocyclo finding on the next run.

The baseline is regenerated per linter instead of per file. Two entries of 170
now carry all five size linters, down from 124; 62 carry three, 22 carry one.

check-lint-baseline.sh fails on a base ref that does not resolve, instead of
reporting success. It compares path, linters and message patterns rather than
path alone, treats rules outside the markers the same way, and allows narrowing
while rejecting widening.

nolintlint now requires an explanation and a specific linter, which CONTRIBUTING
already claimed. Adds pull-requests: read so the patch fetch cannot fall back to
a full run, gofmt -s on the three remaining files, and corrects the gosec and
gocritic counts now that findings are no longer collapsed.
)

The legacy size baseline was generated on macOS. golangci-lint only analyses
files whose build tags match the target, so not one file behind a linux or
windows tag was ever looked at and none of them entered the block. CI lints on
ubuntu, where `lint / install/integrationctl` goes red on
adapters/process/osrunner_tree_linux.go with 21 findings, including a 1332 line
file. Nobody is editing that file; it was simply never in the list.

This did not surface on the Part 0a PR because lint.yml is only reachable
through ci.yml, which triggered on pull_request for main and master, and Part 0a
went into the refactor branch. core-fast.yml in the Part 0b PR is the first
thing that actually ran it.

The six entries come from re-running the size gate under GOOS=linux and
GOOS=windows across the three lint modules, not from hand editing:

  cli/plugin-kit-ai/internal/authoring/scaffold/rename_windows.go
  cli/plugin-kit-ai/internal/promptio/cancel_windows.go
  install/integrationctl/adapters/process/osrunner_tree_linux.go
  install/integrationctl/adapters/process/osrunner_tree_windows.go
  install/integrationctl/agentplugins/adapters/packageview/scratch_windows.go
  install/integrationctl/agentplugins/adapters/packageview/source_windows.go

packageview/source_windows.go at 682 lines is already named in the refactor plan
as out of scope, which is how obvious the omission is in hindsight.

check-lint-baseline.sh reports all six as new, by design. Its own header calls
that out: the script catches accidental widening and pushes the deliberate kind
through review. This is the deliberate kind, and it is the last time the block
grows.

The regeneration requirement is now written down in .golangci.yml above the
block and in CONTRIBUTING.md, and the residual risk that the gate never sees
windows and darwin files at all is recorded as item 13 in the plan's risk list.
#290)

* test(agentplugins): add refactor guardrails for the install core (Part 0b)

Behaviour is untouched. This adds the measurement layer the stacked
installer-core refactor is checked against.

archtest (install/integrationctl/agentplugins/internal/archtest) restates the
depguard import rules as a plain go test, so the layering also holds without
golangci-lint, and measures a per-package budget of client identity references.
The baseline is generated, never hand written:

  cd install/integrationctl && go run ./agentplugins/internal/archtest -update

The plan specified the metric as "domain selector matching ^Client[A-Z][A-Za-z0-9]*$".
Taken literally that also counts domain.ClientID, ClientBinding, ClientSurface
and ClientPackageRevision, which are type references rather than branching: the
budget would grow whenever a signature gains a map[domain.ClientID], and no
package could ever reach zero. The implementation therefore keeps the pattern as
the first filter and then admits only the names domain declares as ClientID
constants, read from the registry itself. The resulting numbers reproduce the
independent count recorded in the plan (cli 89, usecase 40, clientdetect 22).

Golden files freeze what the core produces today for all eleven clients:
planning across four representative envelopes, the compatibility facade,
detection on darwin/linux/windows, activation and deactivation with a fake
command runner including VerifyOnly and unconfirmed previews, and the CLI
--format json dry run. They render every exported field, including the
operational paths the public json tags hide, and normalise volatile roots and
identifiers so a rerun produces no diff.

plan_detected_divergence.json records on purpose that cmd/agentplugins builds
its planner with an empty Detected map while the CLI builds one with a real map,
and that the two disagree about the native Copilot backend. The test fails if
they ever start agreeing, so introducing PlanRequest cannot level this out by
accident.

add_normalize_target_test.go pins the --target vocabulary that domain.ParseClientID
has to preserve: eleven ids, six aliases, case folding, and the lenient
pass-through that turns an unknown name into a lowercased id rather than an error.

CI: core-fast.yml is the merge gate for parts landing in the refactor branch
(lint, test-core with coverage in the job summary, cross build for the three
target platforms, go vet across all five workspace modules). vet-all is there
because test-core does not compile the authoring commands, terminal prompts,
conformance adapter, registry mirror or repotests, and all of them use core APIs
the refactor changes. ci.yml gains a push trigger for refactor/** so the full
lane runs after each merge instead of blocking every part for 10-27 minutes.

* ci: fix two defects the first real core-fast run exposed

`make test-core CORE_TEST_FLAGS=-cover` broke adapters/clientdetect. Its version
probe re-executes the test binary and parses the child's stdout as JSON; under
-cover the child appends "warning: GOCOVERDIR not set" to that stdout, because
the probe deliberately strips the environment and cannot pass GOCOVERDIR down.
The gate is back to a plain `make test-core`, identical to the local preflight,
and coverage moved into a separate informational step that skips that one
package. CORE_TEST_FLAGS is gone again with it.

ci.yml failed at startup on the new refactor/** push trigger. The repository
default workflow permission is contents:read, lint.yml asks for
pull-requests:read so only-new-issues can read the PR diff, and a called
workflow may not request more than its caller holds. The lint job now grants it
explicitly. core-fast.yml already did, which is why its lint legs ran and
ci.yml's did not; the job had never executed before, since ci.yml only
triggered on main and master.

* test(archtest): make the layer rule branch read as written

deny and allow were selected through a nil check that was easy to misread.
Verified by probe: a hujson import in domain, a planner import in ports and a
providers import in usecase each fail their own rule.

* docs(plan): correct the ClientID budget metric in section 7.2

The draft defined it as a regex on the selector name. That also counts
domain.ClientID, ClientBinding, ClientSurface and ClientPackageRevision, which
are type references, so the ratchet would fire on PlanRequest.Detected,
Registry.Lookup and ParseClientID - changes the plan itself requires - and the
DoD criterion "zero ClientID branching" would be unreachable, since usecase and
ports must name that type.

The metric now reads: names the domain package declares as ClientID constants,
resolved by parsing domain itself. That reproduces the independent selector
count already recorded in section 2.1, which is the evidence the regex was a
drafting slip. Later parts reference the corrected definition.

* ci: run the full lane on the refactor base branch only

push: branches used the glob refactor/**, which also matches every part branch
stacked on the base. The result on this branch was four full Required runs of
12-17 minutes, one per push, next to the core-fast run on the same commits -
precisely the double spend section 10 of the plan set out to avoid by saying the
full lane runs "after a part merges into the base branch". The base branch is
now named explicitly.

Section 10 of the plan is corrected in the same commit, in all three places that
quoted the glob, and section 10's test-core row now matches what core-fast
actually does: `make test-core` as the gate, coverage as a separate
informational step, with the reason -cover cannot be a flag on the gate written
down next to it.

* test(providers): add the responding-client half of the lifecycle golden

The golden set so far ran every client against a runner that answers with an
empty result. Eight clients reach their normal outcome that way, but Claude and
Kiro end in their unknown-evidence error and Cline stops at the missing
ownership guard, so the happy path of the three most involved lifecycles was not
pinned at all. Part 7 moves exactly this dispatch into per-client adapters and
the plan rates it the riskiest part, so it needs both halves.

Added, alongside the existing files rather than replacing them:

  activate_client_responds.json
  activate_client_responds_verify_only.json
  deactivate_recorded_ownership.json

Claude gets its `plugin list --json` listing, Kiro an ACP session reporting the
planned server connected (duplexLive, otherwise the reader hits EOF and Kiro
reads that as the agent exiting early), and the removal case carries the native
objects a completed Cline install would have recorded. All eleven clients now
have a recorded happy path and a recorded silent-client path.

archtest: a const spec with its own value ends type inheritance inside a block,
so it can no longer be mistaken for a ClientID identity. No effect today, every
const in domain/clients.go carries its type.
…#292)

* refactor(agentplugins): route the install core through ports (Part 1)

The use case layer no longer reaches for an adapter or the planner package.
Path containment moves behind ports.PathPolicy and planning moves behind
ports.DeliveryPlanner with a domain.PlanRequest, so both are injected instead
of imported.

- ports/paths.go: PathPolicy, implemented only by adapters/pathpolicy.Policy.
  internal/archtest fails the build on a second type carrying the whole method
  set, test files included, and ports/contracttest.RunPathPolicy is the
  mandatory harness: a permissive stand-in would silently drop the symlink and
  escape rejection that guards every destructive operation.
- usecase.Service.Paths and planner.Planner.Paths are required with no default.
  A service or planner wired without one fails fast rather than running with
  weaker containment than the caller assumes.
- ports.DeliveryPlanner.Plan takes domain.PlanRequest and applies the install
  intent itself, so a caller cannot forget the second step. Planner.Detected
  stays as the fallback when the request carries no surface map.
- CommandRunner and its three opt-in capabilities move to ports/runner.go;
  providers keeps aliases. Command and CommandResult stay in the legacy ports
  package, as documented in docs/ARCHITECTURE.md.
- The five use case type assertions become exported interfaces in
  ports/optional.go, with compile-time assertions in providers so a drifted
  signature breaks the build instead of quietly taking the fallback path.
- clientVerifierAvailable moves to providers.Activator behind
  ports.ActivationVerifierClassifier. The client switch travels with it, which
  is why the archtest baseline shows usecase -9 and providers +9.
- usecasetest.NewService and plannertest.NewPlanner wire the production policy
  in one place, so later parts do not repeat this edit across call sites.

Behaviour is unchanged: the Part 0b golden files are byte identical.

* chore(authoring-docs): advance the source pins Part 1 moved

The docs exporter pins a sha256 for every non-test Go file in the construction
packages, and the inventory check rejects one it does not know. Part 1 edited
three pinned CLI files and added domain/planning.go, so the pins advance with
them, the same way dev_session.go advanced in b443eb7.

* fix(agentplugins): close two ways around the PathPolicy gate

Both were found by running real exploits against the gate, not by reading it.

The archtest rule only reported a type that declared the whole method set, so
`struct{ pathpolicy.Policy }` with a single overriding RequireExactPath walked
through it: embedding supplies the other two methods, the type satisfies the
port, a Service accepts it, and the os.Lstat symlink rejection is gone. One
declared contract method is now enough to report. A type that embeds and
overrides nothing still is not reported, because it behaves exactly like the
real Policy. The same change closes the alias variant, since the shape check no
longer reads parameter and result type names: `type s = string` is string.

The contract harness built its escape case with filepath.Join, which cleans, so
the ".." never reached the implementation and the case only asserted "a path
outside base is rejected". A naive policy comparing raw strings with HasPrefix
passed the whole harness. The candidate is now concatenated, and two cases join
it: an unnormalized spelling of the exact managed path has to be accepted, so
the harness catches an implementation that is too strict as well as one that is
too permissive, and a relative candidate to RequireContainedChild has to be
rejected.

The symlink cases move into named subtests. A host that refuses os.Symlink now
skips visibly instead of logging and continuing, which had made the two
strongest negative assertions disappear into a passing run.

docs/ARCHITECTURE.md listed imports for usecase that left out
install/integrationctl/ports. The use case does import it, for
LockManager, and that is not the data-only exception the document already
records, so it is written down as its own.
…Part 2) (#293)

* refactor(agentplugins): add the clients contract and shared helpers (Part 2)

Establishes the extension point the later parts migrate onto, and pays the
DRY debt before any client code moves, so Part 5 relocates deduplicated
files instead of duplicated ones. No behavior changes: the planner,
detection and activation golden files are byte-identical.

New `agentplugins/clients` holds the segregated capability contract
(Adapter, HostDetector, TargetLayout, PlanRefiner, CompatibilityLimiter,
StagingLayout, Projector, Lifecycle, ActivationPreflighter,
AutomaticActivator, ReadOnlyVerifier, RegistryInspector,
PreparedRegistryInspector, SelectionReader, Env, RegistryFinding) plus the
Registry that resolves a client id to its adapter. NewRegistry rejects a
duplicate id and an id domain does not define; All follows
domain.ClientDefinitions order; As[T] is the capability lookup. A nil
Registry stays inert and the dispatchers built on it will fail with
ErrRegistryRequired - resolving nil to "every client" would compile every
adapter into any binary importing a generic package and take the registry
out of the composition root's hands.

`clients/contracttest` carries the harness that compensates for As[T]
being a runtime assertion: RunAdapter today, and RunTraitParity, which
checks a declared client trait against the interface the declaration
promises. The traits land in Part 9, so it ships running on an empty
requirement set; the mechanism itself is covered by tests through the
pure violations functions each Run* reports.

`providers/nativeconfig` moves to `adapters/nativeconfig`. It is a generic
content-addressed kernel with no dependency on providers, and the contract
needs it for clients.Env. It also pulls hujson and atomicfile, which is
why ARCHITECTURE.md now records "close to extractable, one known
exception" instead of claiming the contract is a leaf package.

`clients/shared` collapses the duplicates the audit found:

- six textually identical "only skills and MCP servers" predicates
  (planner.hasOnlyKiroNativeComponents, hasOnlyPortableNativeComponents,
  geminiNativePlanComponents, providers.kiroNativeComponents,
  openCodeNativeComponents, geminiNativeComponents) -> OnlyNativeComponents
- three component-kind predicates (providers.componentKindPresent,
  stager.hasSupported, planner.hasSupportedKind) -> ComponentKindPresent
- three copyString manifest builders (projectOpenAI, projectCursor,
  projectedOpenAIManifest) -> ManifestFromEnvelope with
  WithAuthorObject/WithAuthorNameEmail
- three MCP projection loops (projectOpenAIMCP, projectCursorMCP,
  projectKiroMCP) -> ProjectMCPServers with the openai/cursor/kiro dialects
- five ready-promotion blocks in the planner -> PromoteNativeReady
- three identical native-config activation branches (Cline, OpenCode,
  Gemini) -> one nativeConfigActivation shape in the activator

Every unexported helper the client-specific files reach for moves with
them, exported: JSON decoding and strict objects, the stdio data
contract, path resolution, marketplace naming, registry findings, the
bounded native diagnostic, capacity checks, and the platform-tagged
exclusive rename. Leaving them behind would have closed a
providers <-> clients/<id> import cycle in Part 5.
providers.ManagedMarketplaceName stays exported as a thin wrapper: the
CLI and the root-module repotests use it.

Two depguard rules lock the direction: clients-no-upward stops an adapter
from importing providers, planner, usecase or clientdetect, and
clients-no-concrete-clients stops the contract, its shared helpers and any
client package from importing another client or the assembled registry.
Both are declared for the packages Parts 3-5 create, and both were
verified to fire.

A git mv of an exempt file looks the same as a new exemption to the
shrink-only baseline check, so moves are now declared in
scripts/lint-baseline-renames.txt. The rename only maps the path; the
entry still has to carry the same linters and message patterns.

* fix(lint): verify a declared baseline rename against git

The rename mechanism compared the entry under the new path against the one
the old path carried, and trusted the declaration for everything else. That
left the file as a way to buy amnesty for new code, which is the exact thing
the shrink-only gate exists to stop. Two bypasses were reproducible:

- repoint an existing exemption at an untouched file and declare the pair,
  and the run passes;
- point two exemptions at one new path, and the per-path union in
  compare_rules reads the widened result as unchanged.

A declaration now has to describe a move git can confirm: the old path was
exempt at the base revision and is gone from the working tree, the new path
exists and was not at the base, no two lines name the same file, and
`git diff -M` reports the pair as a rename. A move that also rewrites the
file past the similarity threshold is a rewrite, and a rewritten file does
not keep its amnesty.

The patterns are reduced to literal paths by undoing the anchors and the
`\.` escapes the generator emits; a pattern that is not one literal file is
rejected rather than guessed at. Lines with the wrong field count are named
instead of silently skipped, and a line whose move has already landed in the
base is reported as removable rather than failing, so a leftover cannot block
the next change.

Also stop contracttest.RunTraitParity from passing on a nil registry. All()
on a nil receiver yields nothing, so the check ran over zero adapters and
went green - which is what an unchecked error from NewRegistry leaves behind,
and exactly when the parity test is supposed to speak up.
#294)

* refactor(agentplugins): add per-client detection adapters and the default registry

Moves the eleven detectX bodies out of the generic detector and into one
package per client, each implementing clients.Adapter and
clients.HostDetector. The bodies are transferred as they were: the only
change is that a client reaches the machine through clients.Host instead
of through the detector's own fields. The detection golden files are
byte-identical.

The surface constructors move into the contract rather than into each
client package, because the evidence strings they produce
(executable_on_path, configuration_directory, application_bundle,
application_installation, desktop_entry, editor_extension) are a
cross-client output contract. clients.NewHost builds that implementation
from HostProbes, so the detector and the contract harness share one
copy. Host also gains ResolvedBinarySurface: Kiro and Windsurf resolve a
binary once and use the path both as evidence and as the executable, and
without it they would have to probe PATH twice or restate the evidence
string themselves.

clients/all is the single place that names every adapter, which makes it
the only package that links all of them into a binary. Default builds
the registry on first use and panics on a duplicate or unknown id: that
is a mistake in the list, not a runtime condition, and every caller
would otherwise translate the same error into the same crash.

contracttest.RunHostDetector covers the structural half of detection on
all three operating systems: surface ids are unique and non-empty, an
undetected surface carries no evidence, a selection surface is one of
the reported ones, and the observation is identical across two runs
including the number of probe calls. The probes count LookPath, Lstat
and ReadDir, so an adapter that read the real machine would show up as
non-deterministic. Its own tests drive the pure violations function with
a deliberately broken adapter, so the harness is shown to reject as well
as to accept.

* refactor(agentplugins): route client detection through the registry

clientdetect.Detector loses its switch over ClientID: detect iterates the
injected registry, asks each adapter for the surfaces it observed, and
keeps the generic half - detection status from the selection surfaces,
display name from domain.ClientDefinitions, the version probe and the
stable ordering by client id. The archtest budget for the package drops
from 22 client identity references to zero and it leaves the lint size
baseline; the detection golden files for darwin, linux and windows are
unchanged.

Registry is required rather than defaulted. NewOS keeps its signature and
leaves the field unset, so cmd/agentplugins assigns clients/all.Default
and stays the one place that decides which clients a binary knows about.
Defaulting it in the constructor would have linked every adapter into any
binary that merely detects, which is the service locator the contract
exists to avoid; the new depguard rule and the matching archtest boundary
keep providers, planner and clientdetect from importing clients/all
outside their tests.

The version probe moves into its own file next to the detector. Two
findings the linter reports on the moved lines are fixed there rather
than carried over: the deferred cleanup ignores its error explicitly, and
the trailing-dot trim drops the redundant HasSuffix guard.

clients/all also carries the parity test between the declarative registry
and the adapters: every domain client has exactly one adapter and every
adapter has a definition, and every adapter is run through
contracttest.RunHostDetector.

* test(agentplugins): make the detection harness match what it claims

RunHostDetector said it proved the adapter reaches the machine only
through clients.Host, but the probe counters cannot see past the host:
an adapter calling os.Stat directly left them untouched and passed. The
harness now also requires that nothing comes back detected and that no
executable is reported, since the host answered "does not exist" to
every question - an ambient read that reaches the Detection shows up
there. That is a necessary condition rather than a sandbox, and the
doc comment, the test names and ARCHITECTURE.md now say so instead of
claiming a guarantee.

One repeat only coin-flipped on a map-backed adapter, so an observation
is now taken eight times and each run is compared against the first, in
content, in surface order and in probe counts.

Also records in the plan where the shared Copilot/VSCode logic goes.
They are separate packages with one backend family, fourteen non-test
references to ClientVSCode in providers and planner are shared branches,
and clients-no-concrete-clients forbids an import between the two
packages - so clients/shared is the only legal home, and Parts 5, 7a and
8 now name it instead of clients/copilot.

Two smaller corrections: the layer table prose still claimed the adapter
row had no rule, and SelectionSurfaceIDs was documented with Windsurf
channels as its example although Claude is its only user.
@777genius
777genius added this pull request to stack #297 September 18, 2026 08:11
* docs(plan): finalize Part 12 contract module plan after review

Rewrites the Part 12 draft with the 13 review corrections: the nativeconfig
DTO-split churn is 193 lines (neutralized by a 22-line alias block in the
implementation package), providers.Activator.NativeConfig and its five
construction sites are in scope, the clients depguard rules are deny lists so
Part 12a adds a rule instead of removing an allow, out-of-tree fitness is
proven by GOWORK=off rather than an in-repo import, and five CI surfaces that
would silently stop seeing the contract get a concrete workflow edit each.

Adds a spec for the guard test to land now, before Part 5, and records a
finding neither the draft nor the review had: domain's external test package
imports adapters/pathpolicy, a third in-monorepo edge that would pull
golang.org/x/text and a module cycle into the new module's require block.

Revises the forecast down: modularity 7.5-8 with an explicit caveat that
clients/shared stays in the monolith, plan reliability and confidence 7/10.

* test(agentplugins): guard the contract layer's dependency closure

domain, ports and clients are the three packages Part 12 will extract
into their own Go module. TestContractLayerDependencyClosure fixes
today's three internal-repo edges leaving that layer (ports ->
install/integrationctl/ports, clients -> adapters/nativeconfig, and
domain's identity_portable_test.go -> adapters/pathpolicy) plus the
full transitive closure and external module set they pull in, so a
new dependency introduced anywhere in Part 5-9 fails on the
introducing PR instead of surfacing at the start of Part 12.

See docs/plans/installer-core-part-12-contract-module.md §12.1.G for
the guard test's spec and §12.1(c) for the dependency snapshot it
enforces.

* test(agentplugins): sweep contract-layer deps across GOOS

The guard test only saw the host platform, so a new Windows-only
external module in nativeconfig would pass on macOS/Linux CI. Recompute
the closure for linux, darwin and windows and record golang.org/x/sys
in the baseline.

* docs(plan): attribute the Windows x/sys edge to nativeconfig only

The guard-test review found the plan still listed lock_windows.go as
stdlib-only and blamed atomicfile for hiding golang.org/x/sys. Only the
nativeconfig Windows files import that module; host-platform CI is the
gap, not go list itself.
…#304)

* refactor(agentplugins): planning through the client registry (Part 4)

planner.Plan loses its switches over ClientID. The pipeline is fixed and
generic now - start from the declarative capabilities, apply the two
rejections the registry alone can decide, resolve the target, decide the
components, apply the catalog verdict and the package diagnostics, then
let the client speak. The archtest budget for the package drops from 44
client identity references to zero, planner.go leaves the lint size
baseline, and every golden plan and compatibility file is byte-identical,
including plan_detected_divergence.json.

Seven named planning stages rather than one refiner. A single RefinePlan
could not carry the existing behaviour: the order of the warnings and
user actions a plan renders is part of the observable contract, and the
client-specific decisions do not all happen at the same point. So each
stage is named for where it runs. NativeRegistryLayout: VS Code records
the sibling Copilot registry instead of its own. PlanPrecondition: Claude
refuses to plan without its CLI, before a target is resolved, so the
rejection never carries resolved paths. TargetLayout: Claude and Cursor
deliver into the directory the client already reads. LocalPreparation-
Authorizer: ChatGPT accepts a personal Context7 receipt in place of
pinned catalog evidence. PlanQualifier: ChatGPT rejects a package whose
MCP servers no registered app binding covers, ahead of the generic "no
usable components" verdict. PlanRefiner: readiness promotions, user
actions, warnings. PreparationRefiner: the prepare install intent, kept
separate because ApplyInstallIntent is also applied on its own to a plan
that was already built. A client implements only the stages it speaks in.

Three branches become declarative instead of moving into an adapter,
because the planner needs them before it has anything to dispatch to.
"ChatGPT plans even when it is not installed here" is
ClientDefinition.PlansWithoutHostPresence. "An app diagnostic destroys a
component" is capabilities.AppSupport != SupportUnsupported, which is
ChatGPT and only ChatGPT today. "A declared sse server the client cannot
take gets a named reason rather than the generic one" is now any client
that does take some other MCP transport, which is Codex and OpenCode
today, and stays the generic reason for a client that takes no MCP at
all. Each is equivalent on the current registry - the golden files pin
that - and each stays correct as the registry grows.

domain/directory_context7_preparation.go, the branch the plan added to
this part as edit F-2, is resolved by declaring the relationship rather
than by adding a boolean trait. ClientDefinition gains
DirectoryPreparationPurpose: the single bounded resolve purpose a client
may acquire source under, empty for every client but ChatGPT. The
validation asks whether the target client declared the purpose the
request carries, so an unknown purpose matches no client and is rejected
for that reason instead of by name. A trait flag would have said "this
client is allowed a preparation purpose" without saying which, leaving
the purpose constant in domain anyway.

Copilot and VS Code share the promotion rule through clients/shared, as
Part 3 recorded: PromoteBackendReady marks a plan ready when the CLI that
installs on the client's behalf was found, and the two adapters differ
only in which executable they resolve for it - its own for Copilot, the
backend sibling's for VS Code. domain.BackendSiblings replaces the
hardcoded Copilot/VS Code pair in DetectedPhysicalClient and in
PlanInput.BackendSibling.

The planner facade keeps its names for callers outside the core
(Capabilities, Compatibility, ClientCompatibility, ApplyInstallIntent,
DetectedPhysicalClient, KiroPrepareAction, ChatGPTAppBindingAction; the
last two now re-exported from the adapters that own the text).
Compatibility and ApplyInstallIntent take the registry as their first
argument, because they are package-level and there is no planner value to
read one from; defaulting it would have linked every adapter into any
binary that merely reports compatibility. cli/internal/authoring is its
own entry point with no composition root above it, so it names the full
set there.

contracttest.RunPlanRefiner runs against every adapter in clients/all
that implements PlanRefiner, on a viable plan and on an unsupported one:
the plan identity comes back unchanged, an unsupported plan is never
promoted, and refining twice equals refining once. Verified by breaking a
refiner deliberately - all three violation classes are reported.

Two findings on the new lines are fixed rather than carried: the pipeline
returned `plan, refiner.RefinePlan(ctx, input, &plan)`, where Go does not
specify that the mutation is visible in the returned copy, and three
moved error strings that now start a sentence lead with an article, the
form claude_probe.go already uses.

* fix(authoring): hand the installer fixtures a client registry

The three authoring fixtures that drive the real add command through
agentpluginscli.App build the planner from App.ClientRegistry, which this
part made required, so they failed with "client registry is required"
before reaching any assertion: TestGeneratedPackagesReachExistingInstaller-
Planner, TestPackedInstallerSourceHarness and
TestPackedInstallerAssessmentBoundaries.

They are skipped on macOS - writable native authoring needs Linux or
Windows - so the local run showed nothing and only the Authoring
workflow caught it. The other App literals in the tree construct the
command tree for discovery and never plan, which is why they have always
left the installer dependencies unset.

* docs(plan): warn Part 7c off depending on the concrete nativeconfig.Kernel type

Part 12 (planned after Part 11) will replace this with a narrow ports
interface. Flagging it now, while the constraint costs nothing, avoids
a rewrite later.

* refactor(agentplugins): inject the client registry into authoring too

readiness.Compatibility named clients/all itself, which linked all eleven
adapters into plugin-kit-ai: the authoring binary went from 2 client
packages to 14 and grew ~78 KB. That is the service locator edit A-3
forbids, and the justification given for it - "authoring has no
composition root above it" - was simply wrong. commands.App is one, and
it is assembled in three mains.

commands.App now carries the registry and hands it down; the three mains
name the set. The dependency count does not fall back to 2 and cannot:
the ChatGPT and Windsurf limitations a compat report prints moved into
the adapters in this part, so a binary that prints them has to link
them. What changes is who decides - a main rather than a library - and
the cost is now visible where it is paid.

depguard rule dispatchers-take-an-injected-registry becomes
libraries-take-an-injected-registry and covers cli/plugin-kit-ai/internal
as well, mirrored by a new archtest boundary. Both were checked against a
deliberately reintroduced import.

App.ClientRegistry stays a runtime invariant, so
TestPlanningFailsClosedWithoutAClientRegistry drives add through an App
without one and asserts the error names the missing registry rather than
a panic, and checks the doctor path degrades instead of crashing. It is
the local version of the check that previously only the Authoring
workflow could make. The authoring fixtures that run compat get a
registry for the same reason.

Also from review:

- contracttest.RunPlanRefiner runs unconditionally per adapter. The
  "if it implements PlanRefiner" guard turned a renamed method into a
  silent skip, which is the failure the harness exists to catch.
- domain pins that every declared DirectoryPreparationPurpose is a known
  constant, so a typo cannot quietly un-declare a client.
- Three branches that no test reached: Claude without its CLI (rejected
  before a target is resolved), Copilot without its CLI (not promoted),
  and the personal ChatGPT mapping, accepted and rejected both ways.
- The plan no longer claims the planner facade signatures are unchanged,
  and no longer asks for a domain archtest budget the metric cannot
  produce. The three reworded error strings are recorded as a named
  exception instead of an unmentioned one.
…ter (Part 5 probe) (#305)

* refactor(agentplugins): move Kiro native and ACP into the client adapter

Part 5 starts with Kiro as the probe: filesystem mutation, ACP verification,
and pipe evidence live in clients/kiro, split under the file-length gate.
Skill digest and object-map helpers move to clients/shared so Gemini, OpenCode,
and Cline do not import Kiro. Providers call the exported Kiro surface until
Part 8 turns on generic-no-concrete.

* fix(agentplugins): split the Kiro adapter so the install-core lint gate can land

The moved files still tripped the whole-file size gate, and new-file
changed-line lint treated every product-name error as ST1005. Extract the
units and keep the golden-pinned wording without wrapping the original
causes.
…ckages (Part 5 remainder) (#307)

* refactor(agentplugins): move remaining native adapters into client packages

Finish the Part 5 file move with 1:1 git mv so size-gate exemptions travel
with the files. Keep Activator/Stager tests in providers so client packages
do not import upward.

* fix(lint): close the changed-line findings on the Part 5 remainder move

Group the Codex test imports, give the exported Claude probe errors a
leading article, and switch Cline object-kind validation so QF1003 is
quiet without splitting the native files.
…ayout (Part 6) (#308)

Stager loses its ClientID switch. The generic pipeline copies, sanitizes,
and digests; each client adapter projects into the sanitized tree and
returns the objects it owns. ChatGPT writes .app.json itself. Claude
keeps staging beside the watched skills root via StagingLayout.
… (Part 7a) (#309)

* refactor(agentplugins): route CLI-registry lifecycle through adapters (Part 7a)

* fix(agentplugins): close Part 7a lint and fail-closed verifier DIP

New adapter paths must wrap both fallback errors, drop unused helpers, and treat a missing registry as no verifier so lifecycle dispatch stays fail-closed.
…(Part 7b) (#310)

* refactor(agentplugins): route Kiro ACP lifecycle through the adapter (Part 7b)

Move prepare, duplex preflight, native mutation and ACP observation into the Kiro adapter so Activator dispatches by registry instead of a ClientKiro switch.

* fix(agentplugins): share the registry-required sentinel on Activator

Dispatchers should fail closed with the same clients.ErrRegistryRequired value, including the boolean lifecycle predicates a leftover native client would otherwise claim.
…s (Part 7c) (#311)

Move Cline, Gemini, OpenCode and Windsurf activate/deactivate onto registry adapters and drop the leftover ClientID switch from Activator. Native-config clients use Env.NativeConfig by value through Apply/ApplyBatch.
…ters (Part 8) (#312)

Move RegistryInspector/PreparedRegistryInspector into client packages and
enable generic-no-concrete so providers and planner no longer import adapters.
…ientTraits (Part 9a) (#313)

* refactor(agentplugins): replace ClientID switches with declarative ClientTraits (Part 9a)

Installer policy now lives on the client table, so usecase and domain stop naming Codex, Claude, Copilot, or ChatGPT and a new client is a row plus contracttest parity rather than another switch.

* fix(agentplugins): wrap both repair verify errors and drop stale trait-parity comments

errorlint rejects %v on the new DisplayName format string, and the Grok nits were leftover Part 9 wording plus Allows claiming Validate's automatic exception.
…phase methods (Part 9b) (#314)

Extract-method the four remaining usecase monoliths so service.go, group.go, repair.go, and remove_group.go can leave the size baseline without changing call order or group goldens.
…position (Part 10) (#315)

* refactor(agentplugins): inject planner and client traits into CLI composition (Part 10)

Move ClientID aliases and CLI client policy behind domain traits and the
composition-root Planner/Targets so commands stop reconstructing core internals.

* fix(cli): close new-file lint on the Part 10 add extract

The extracted add helpers left the size baseline, so errcheck, errorlint,
gocritic, goimports, and unconvert now apply to those lines.
…ansitional aliases (Part 11) (#316)

Detection is request-scoped, generic packages no longer name clients, and in-scope files leave the size baseline so adding a client stays three edits plus contracttest.
* refactor(agentplugins): extract the install core into a nested Go module

Give agentplugins its own go.mod so GOWORK=off CI, coverage, and vuln scans
see the tree; keep import paths and a one-way replace to the parent.

* fix(agentplugins): point leftover parent-relative tests at the nested module

Keep the release-contract ratchet on the nested go test/vet lines so dropping
the module from Makefile cannot stay green.
#318)

* fix(agentplugins): attest the nested module in authoring-docs factory pins

Required and Coverage failed because go.work now names a module the docs
fixture did not copy. Keep the v0.1.65 overlay attesting that tag's bytes.

* docs(agentplugins): name current-only files the v0.1.65 overlay drops

The ENOENT path also drops domain/planning.go, not only the nested module
go.mod.
workflow_call hides pull_request from golangci-lint-action only-new-issues, so Required on the architecture PR linted every module. Match make lint and fix the ST1005/unused findings that are actually new versus main.
…ify, and identity (#320)

* docs(agentplugins): record both composition roots and the merge-base lint gate

ADR 0007 and ARCHITECTURE claimed cmd/agentplugins was the only production clients/all importer; authoring's plugin-kit-ai binary is a second root. Coverage now cds into the nested module, and the plan matches the lint.yml that #319 actually shipped.

* fix(agentplugins): thread one nativeconfig kernel through activate, verify, and identity inspect

Activate wrote through env.NativeConfig while Verify and registry inspect constructed nativeconfig.New(), so an injected kernel never observed its own writes.

* fix(agentplugins): fail closed on a missing nativeconfig kernel

An omitted NativeConfig used to construct a second OS kernel, so production and tests could not tell a wired kernel from a default. Zero Kernel now fails Inspect/Apply; Kiro re-runs duplex preflight before native writes; Makefile/core-fast cd into the nested module under GOWORK=off.

* fix(agentplugins): fail closed when a native client has no projector

Staging a native or native-config client without As[Projector] used to succeed with empty native objects. Claude and ChatGPT Activate now run PreflightActivation themselves so a skipped dispatcher lookup cannot bypass the probe.

* fix(agentplugins): refuse skill-only native writes without a kernel

A zero nativeconfig kernel skipped ApplyBatch on Cline/OpenCode skill-only
paths, so omitted NativeConfig still mutated the host tree. Require FileIO
before those writes and keep GOWORK=off test-core inside nested modules.

* fix(agentplugins): refuse Gemini skill writes without a kernel

Gemini installs skills before ApplyBatch, so a zero kernel still mutated
the host tree and only failed on the later MCP batch. Require FileIO on
the Gemini and Windsurf native entry points before any skill or config IO.

* fix(agentplugins): inspect Cline and OpenCode native identity before commit

Always-Clear InspectNativeRegistry let colliding skills and MCP names pass the pre-commit gate. Mirror Gemini: empty registry root is indeterminate, and a present host name is a collision.

* fix(agentplugins): allow missing OpenCode objects during identity inspect

Repair must observe identity after a host wiped managed MCP entries. Exact verify stays on Activate; identity inspect now matches Gemini's allow-missing check.

* fix(agentplugins): allow missing Windsurf MCP during identity inspect

Wiping a managed Windsurf entry must still be repairable. Identity now uses allow-missing verify like Gemini; Activate still requires exact ownership.

* test(agentplugins): cover Windsurf RepairGroup after wiped native MCP

Single-client Repair skips identity inspect. RepairGroup and Update are the production gates that must restore a missing owned Windsurf entry.

* fix(agentplugins): inspect OpenCode and Windsurf host identity without the package

RepairGroup refused a missing managed directory because inspect still verified the live ActivePath projection. Host-only inspect matches Cline and Gemini so a wiped package can be restaged.
… commit

Identity inspect now classifies a foreign host MCP key as unmanaged before UpdateGroup or RepairGroup mutate managed bookkeeping. The hosted OpenCode lifecycle still expected ActivationFailed after commit.
… repair

Update now refuses a foreign host MCP key before commit, so the fixture 3.0.0 tree is not the applied revision. Restore the managed package so repair can observe that collision.
…repair

Copying the managed package directory left repair preflight comparing the published artifact to the recorded source envelope. Restore the fixture snapshot from before the 3.0.0 probe.
Root module is go 1.22, so stdversion rejects os.CopyFS. Snapshot and restore the applied source with filepath.Walk.
@777genius
777genius marked this pull request as ready for review September 19, 2026 09:27
@777genius 777genius changed the title WIP: installer core clean architecture refactor refactor: installer core clean architecture refactor Sep 19, 2026
@777genius
777genius merged commit 83ace7b into main Sep 19, 2026
76 checks passed
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.

1 participant