Skip to content

6b: Go changes tracking the upstream merge - #5

Open
JEHoctor wants to merge 8 commits into
go-port-6b-upstream-mergefrom
go-port-6b-restore-parity
Open

JEHoctor wants to merge 8 commits into
go-port-6b-upstream-mergefrom
go-port-6b-restore-parity

Conversation

@JEHoctor

Copy link
Copy Markdown
Owner

Stacked on #4 (which is stacked on #3). Restores the Go port to parity with the bash tree after the upstream merge: the harness goes from 0/27 to 33/33, and every bash-backed parity suite is green again.

One commit per upstream feature, so each can be read next to the upstream PR it tracks:

Commit Upstream
Pins + the flow-style agent: {} stub VirtusLab#100, VirtusLab#99
Stack environment entries, merge semantics (uv TLS) VirtusLab#91
JetBrains stack plugins VirtusLab#79
--features strict-network + settings.local.json scaffold VirtusLab#106, VirtusLab#96
GitHub Copilot CLI agent VirtusLab#94
upstream_ca_bundles VirtusLab#92
restart-proxyrestart with agent netns re-link VirtusLab#93
Embed test derived from disk; plan status

Everything else upstream shipped in that range was template- or image-only and flows through the embed untouched.

Things worth a look:

  • appendContent in internal/compose/file.go: yaml.v3 keeps a template's agent: {} in flow style when populated, yq flips it to block. Reset only for an empty flow node, so a non-empty one still keeps its style as under yq.
  • restart-proxy is kept as a hidden deprecated alias; the bash dropped it. Cheap, and it keeps scripts working.
  • The upstream_ca_bundles path isn't reachable from the harness (no bundle under a throwaway HOME), so it has its own parity test with fixture bundles split across both settings files.
  • Harness and matrices gained copilot and strict-network rows (27 → 33). The dump script now enumerates agents from sct_available_agents, so a fifth agent can't be missed.

Merge order: this into #4's branch first (turns #4 green), then #4go-port, then #3main.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YKma722KMnAX3LcDLUYDQ5

JEHoctor and others added 8 commits September 15, 2026 10:07
…tusLab#99)

Upstream pinned the mitmproxy image (SCT_MITMPROXY_VERSION, rendered
into both the template placeholder and the secret-provider image tags)
and the rtk installer script and binary. The version lives in
compose.MitmproxyVersion, with a contract test against
images/mitmproxy.env mirroring cli/test/compat/mitmproxy_version.bats;
the rtk block is regenerated from bash.

The compose-agent.yml split (VirtusLab#99) leaves compose-all.yml declaring
`agent: {}` in flow style. yaml.v3 preserves that style when children
are added, rendering the populated service on one line; yq switches an
empty flow collection to block style as soon as it gains content.
appendContent now does the same, and only under that condition, so a
non-empty flow node still keeps its style as it would under yq.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKma722KMnAX3LcDLUYDQ5
The python stack now sets UV_SYSTEM_CERTS=1 on the agent service so uv
trusts mitmproxy's intercepting CA. Upstream reworked the environment
plumbing to make room for it: services.agent.environment is merged
(appended to) rather than set, with the stack entries written before the
agent's. SetAgentEnvironment becomes MergeAgentEnvironment and Generate
follows the bash call order, which decides the entry order in the file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKma722KMnAX3LcDLUYDQ5
Stacks now carry a JetBrains Marketplace plugin id, the counterpart of
the VS Code extension for the JetBrains devcontainer path. Generate fills
the `"plugins": []` array that the JetBrains customizations block
declares, after CustomizeJSON has emitted it. Stacks whose language
support is bundled, or whose JetBrains IDE is a standalone product with
no IntelliJ plugin, contribute nothing and leave the array empty.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKma722KMnAX3LcDLUYDQ5
, VirtusLab#96)

`--features strict-network` (or SANDCAT_STRICT_NETWORK=true) replaces
the project template's allow-all-GET wildcard with one `{"preset": s}`
entry per resolved stack, expanded to concrete rules by the mitmproxy
addon at start so the domain lists track the sandcat version. That path
goes through `yq -o=json` in the bash and therefore reformats the whole
file; jsonfile reproduces the layout, and a parity test covers the plain
copy, strict with stacks, and strict with none.

init also scaffolds an empty .sandcat/settings.local.json — the
highest-precedence layer in the addon's settings merge and gitignored by
the Sandcat block — and never overwrites one that exists, since it holds
real credentials. The harness gains three strict-network cases: 30/30.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKma722KMnAX3LcDLUYDQ5
Fourth supported agent. The table entry carries its extension, token
help, mitmproxy addon and host config paths; the Dockerfile, home-prep
and user-init fragments are captured from bash like the others, and the
dump script now enumerates agents from sct_available_agents so a fifth
one cannot be missed. The compose mounts follow upstream: mcp-config.json
read-only, session-state read-write because Copilot CLI writes session
events there and fails with EROFS otherwise.

Harness and parity matrices gain copilot rows: 33/33.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKma722KMnAX3LcDLUYDQ5
Users behind a corporate TLS interceptor can list PEM bundles under
`upstream_ca_bundles` in user settings or the project's
settings.local.json. init validates each (absolute, readable, contains a
certificate block — the document is left untouched on any failure),
bind-mounts them read-only into mitmproxy, and prepends their
installation to the entrypoint. The install runs into both the OS store
and certifi's bundle, because mitmproxy reads its trust store from
certifi; and it is joined with `|| exit 1;` rather than `&&` so it stays
outside the entrypoint's backgrounded list and fails loud.

The harness never exercises this (no bundle under a throwaway HOME), so
it gets a dedicated parity test with fixture bundles split across the
two settings files, plus a rejection test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKma722KMnAX3LcDLUYDQ5
)

The command restarts the agent as well when it was running: the agent
uses network_mode: service:wg-client, which Docker resolves to a netns
fd at start, so after wg-client restarts the agent's fd points at a
torn-down namespace and every outbound connection breaks. The re-link
waits for wg-client to be healthy first.

Unlike the bash, the old name is kept as a hidden deprecated alias so
existing scripts and docs don't break on upgrade.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKma722KMnAX3LcDLUYDQ5
Upstream added four template files (compose-agent.yml, java-env.sh, the
copilot addon and user-settings template). The hand-maintained expected
list in embed_test.go would have kept passing without them, so it now
walks cli/templates and requires the embedded tree to match file for
file and byte for byte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKma722KMnAX3LcDLUYDQ5
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