Skip to content

chore(wrappers)!: drop env-allowlist, env-extra, allow-protocol-skew from wrappers (sync with engine)#31

Merged
manojp99 merged 3 commits into
mainfrom
feat/drop-env-and-skew-from-wrappers
Jun 3, 2026
Merged

chore(wrappers)!: drop env-allowlist, env-extra, allow-protocol-skew from wrappers (sync with engine)#31
manojp99 merged 3 commits into
mainfrom
feat/drop-env-and-skew-from-wrappers

Conversation

@manojp99

@manojp99 manojp99 commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Catches both wrappers up to the engine surface PR #27 shipped. The engine dropped these three argv flags in #27 but the wrappers were never updated — they kept emitting them when consumer fields were set, causing callers that exercised those fields to fail at runtime with click UsageError, exit 2.

This PR is wrapper-only. Engine untouched.

The gap this fixes

After PR #27 merged on main:

Surface Engine (post-#27) TS wrapper before this PR Python wrapper before this PR
--env-allowlist Removed Still emitted Still emitted
--env-extra Removed Still emitted Still emitted
--allow-protocol-skew Removed Still emitted Still emitted

Wrapper consumers that set envAllowlist / envExtra / allowProtocolSkew got runtime UsageError failures. The wrapper API also still advertised these fields as valid — silently misleading. Surfaced when planning the post-#27 release version story.

What's removed

TypeScript wrapper (BREAKING):

Python wrapper (BREAKING):

  • env_allowlist, env_extra, allow_protocol_skew kwargs/fields from spawn_agent / assemble_argv / SessionHandleParams

Guardrails added:

  • TS: @ts-expect-error compile-time blocks asserting the fields are gone + runtime not.toContain assertions
  • Python: pytest.raises(TypeError) kwarg-rejection tests + flag-not-emitted assertions

Migration

Old New
wrapper.spawnAgent({ envAllowlist: [...], envExtra: {...} }) Wrapper consumer computes env itself and sets $AMPLIFIER_AGENT_CONFIG in subprocess env (or passes --config <path> per turn). Engine reads from host config — no per-call argv emission needed.
wrapper.spawnAgent({ allowProtocolSkew: true }) Set allowProtocolSkew: true in the host config JSON file ({ "allowProtocolSkew": true }). Engine reads it from the same place as the other config keys.
Mode A amendment §3.2 "wrapper-set env diagnostic" via argv Moved entirely to host config layer (PR #27 D10)

Tests

Suite Pass Fail
TypeScript wrapper 66/66 (was 63 — +3 new guardrails) 0
Python wrapper 54/54 (was 48 — +6 new guardrails) 0
Conformance TS 4 1 (pre-existing — initialize-with-mcpservers runner test, unrelated)
Conformance Py 4 1 (pre-existing — same fixture name issue)
Engine (uv run pytest --ignore=wrappers) 512 + 3 skipped 4 (verified identical baseline on main)

Engine suite verified unchanged — this PR only touches wrapper code.

Commits

8e71da8 chore(wrapper-ts): rebuild dist after wrapper API removals
00c9a7a chore(wrapper-py)!: drop env_allowlist, env_extra, allow_protocol_skew from spawn_agent + assemble_argv
796f10d chore(wrapper-ts)!: drop envAllowlist, envExtra, allowProtocolSkew from AssembleArgvInput + argv emission

Conventional Commits with ! for breaking changes; BREAKING CHANGE: footers document the migration paths.

Cross-repo follow-up

amplifier-module-provider-nc's adapter spawnAgent() call may still pass envAllowlist / envExtra / allowProtocolSkew. Will break against post-this-PR wrappers. Same shape as Phase 1's hostCapabilities NC follow-up and PR #29's --mcp-config-path NC follow-up.

Migration for NC adapter: stop passing these three fields; if env injection is needed, compute it adapter-side and set $AMPLIFIER_AGENT_CONFIG (or write a per-turn host config) before spawning the engine subprocess.

Why strict (no wrapper tolerance)

Matches Phase 1 + PR #29 posture. The engine already rejects these flags loudly at runtime — keeping the wrapper fields would extend a lie about what works. Removing the fields surfaces the migration at compile time (TS) / signature-check time (Python) instead of silently at the first call site that exercises the dead path.

Supersedes / amends

  • PR feat: host config layer + drop hostCapabilities surface #27's design docs/designs/2026-06-01-host-config-layer-revisit.md D10 argv surface table — wrapper side of the table is now caught up.
  • Mode A amendment §3.2: the path that read --env-allowlist / --env-extra via wrapper argv emission is fully gone end-to-end.

Manoj Prabhakar Paidiparthy and others added 3 commits June 3, 2026 00:01
…om AssembleArgvInput + argv emission

The engine removed the --env-allowlist, --env-extra, and
--allow-protocol-skew argv flags in PR #27 (host config layer). The
TypeScript wrapper was still emitting them when the corresponding
AssembleArgvInput / SessionHandleParams / SpawnAgentParams fields
were set, which made engine click reject the invocation with UsageError
(exit 2) for any wrapper consumer that supplied them.

This commit removes:
- envAllowlist, envExtra, allowProtocolSkew from AssembleArgvInput
  and the three argv.push(...) blocks in assembleArgv()
- envAllowlist, envExtra, allowProtocolSkew from SessionHandleParams
  and the threading through to assembleArgv()
- allowProtocolSkew from SpawnAgentParams and the threading through to
  new SessionHandle(...)

SpawnAgentParams.env = { allowlist, extra } is preserved unchanged - the
wrapper still composes the subprocess environment via buildEnv(). Only
the FORWARDING of those values as argv flags to the engine is removed.

argv-builder tests are extended with @ts-expect-error compile-time
guardrails and runtime negative assertions for all three flags, mirroring
PR #29's removal pattern for --mcp-config-path.

NC follow-up: the NC adapter (amplifier-module-provider-nc) may pass
envAllowlist / envExtra / allowProtocolSkew to spawnAgent(); a follow-up
adapter PR will catch it up.

BREAKING CHANGE: SpawnAgentParams.allowProtocolSkew,
SessionHandleParams.envAllowlist / envExtra / allowProtocolSkew, and the
corresponding AssembleArgvInput fields are removed. Hosts that need the
skew override now set host_config.allowProtocolSkew: true in the JSON
config file. Hosts that need custom env composition either set
$AMPLIFIER_AGENT_CONFIG in the subprocess env or pass --config <path>
per turn.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…w from spawn_agent + assemble_argv

The engine removed the --env-allowlist, --env-extra, and
--allow-protocol-skew argv flags in PR #27 (host config layer). The
Python wrapper was still emitting them when the corresponding kwargs were
set, which made engine click reject the invocation with UsageError
(exit 2) for any wrapper consumer that supplied them.

This commit removes:
- env_allowlist, env_extra, allow_protocol_skew kwargs from assemble_argv
  and the three argv.extend(...) / argv.append(...) blocks
- env_allowlist, env_extra, allow_protocol_skew fields from
  SessionHandleParams (and the unused `field` import that they required)
  plus the threading into assemble_argv
- allow_protocol_skew kwarg from spawn_agent and the threading into
  SessionHandleParams

spawn_agent(env={"allowlist": ..., "extra": ...}) is preserved unchanged
- the wrapper still composes the subprocess environment via build_env().
Only the FORWARDING of those values as argv flags to the engine is
removed.

test_argv_builder is extended with three TypeError-rejected kwarg tests
and three "flag not emitted" negative assertions, mirroring PR #29's
removal pattern for --mcp-config-path.

NC follow-up: the NC adapter (amplifier-module-provider-nc) may pass
env_allowlist / env_extra / allow_protocol_skew to spawn_agent(); a
follow-up adapter PR will catch it up.

BREAKING CHANGE: spawn_agent.allow_protocol_skew,
SessionHandleParams.env_allowlist / env_extra / allow_protocol_skew, and
the corresponding assemble_argv kwargs are removed. Hosts that need the
skew override now set host_config.allowProtocolSkew: true in the JSON
config file. Hosts that need custom env composition either set
$AMPLIFIER_AGENT_CONFIG in the subprocess env or pass --config <path>
per turn.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Regenerates wrappers/typescript/dist/ to reflect the source removals in
796f10d (drop envAllowlist, envExtra, allowProtocolSkew from
AssembleArgvInput / SessionHandleParams / SpawnAgentParams + argv
emission).

Mirrors PR #29's pattern of committing the rebuilt dist alongside the
source change so consumers using the published package see the API
narrowing immediately. No additional source changes.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
@manojp99 manojp99 merged commit 07e6b1b into main Jun 3, 2026
1 of 3 checks passed
manojp99 added a commit that referenced this pull request Jun 3, 2026
…#27, #29, #31) (#32)

* fix(conformance): rename runner refs to initialize-with-mcp-config-path (post-#24)

PR #24 renamed the wire-shape fixture from
``initialize-with-mcpservers.yaml`` to
``initialize-with-mcp-config-path.yaml`` but left three hardcoded
references to the old name behind:

  * wrappers/conformance/test/runner-ts.test.ts (TS conformance suite)
  * wrappers/conformance/tests/test_runner_py.py (Py conformance suite)
  * tests/test_phase_2_1_exit_gate.py (engine-side fixture-set guard)

All three have been failing since PR #24. The conformance suites
showed up as "1 pre-existing failure each" in PRs #27, #29, and
#31, so wrapper/engine drift could land unseen during the entire
window in which we did most of the v0.3.0 argv cleanup -- the
exact class of bug the conformance suite is supposed to catch.

This commit restores the baseline to green by pointing each
reference at the surviving wire-protocol fixture name. No fixture
data changes, no engine logic changes.

Verification (this commit, host machine):
  * wrappers/conformance/ (TS): 5 passed (was 4 passed, 1 failed)
  * wrappers/conformance/ (Py): 5 passed (was 4 passed, 1 failed)
  * tests/test_phase_2_1_exit_gate.py: passes (was failing)

Out of scope (separate cleanup, noted for the PR body):
  * tests/cli/test_mode_a_v2_envelope.py still has 3 pre-existing
    failures referencing the removed ``--mcp-servers`` flag.
    Not touched here per the conformance-restore PR scope.

* chore(conformance): align version_skew remediation text with post-#27 host-config surface

PR #27 dropped the --allow-protocol-skew argv flag and moved protocol-skew opt-in into the host config file (allowProtocolSkew: true, surfaced through --config). The engine's real protocol_version_mismatch remediation string was updated in lockstep (src/amplifier_agent_lib/engine.py:160-163).

The version_skew wire-shape fixture's scripted server response still carried the old 'pass --allow-protocol-skew' remediation text, drifting it from current engine behavior even though no assertion in the fixture exercises the field directly. Update the scripted response to match the engine's current text so the fixture remains an honest exemplar of the wire-protocol surface post-#27/#29/#31.

Companion to PR #31 fixture sweep. No engine logic changes, no assertions changed, no test outcome changes.

* test(conformance): add baseline + protocol-skew-override wire-shape fixtures

Extend the conformance suite with two wire-protocol fixtures that lock in the post-cleanup surface and the previously-uncovered override branch of the version-skew contract:

* initialize-baseline.yaml -- canonical minimum init + turn/submit + result/final flow with only protocol-required params (no mcpConfigPath, no allowProtocolSkew, no hostCapabilities, no envAllowlist, no envExtra). Locks in the wire shape that survives PR #27 (host config + drop hostCapabilities), PR #29 (drop --mcp-config-path argv), and PR #31 (drop env-allowlist / env-extra / allow-protocol-skew from wrappers). Any future re-introduction of those legacy fields on the wire must be an intentional, reviewed addition rather than silent drift.

* initialize-with-protocol-skew-override.yaml -- the 'permits the handshake' branch of design §8 D6, companion to version_skew.yaml which covers only the strict-refuse branch. Client sends allowProtocolSkew=true (now sourced from the host config file, not from a --allow-protocol-skew argv flag) and a mismatched protocolVersion; server returns a successful sessionState instead of protocol_version_mismatch.

Both new fixtures are wired into the TS and Python conformance runners and acknowledged in the two fixture-set guard tests (tests/test_protocol_conformance_fixtures.py and tests/test_phase_2_1_exit_gate.py).

Scope note: the conformance runners use scripted JSON-RPC wire replay (ScriptedTransport) -- they do NOT spawn the engine subprocess. Argv-level 'loud failure' invariants for the dropped flags (--host-capabilities, --env-allowlist, --env-extra, --allow-protocol-skew, --mcp-config-path) are already locked in by the engine-side click-CliRunner tests at tests/cli/test_drop_host_capabilities.py and tests/cli/test_drop_mcp_config_path_flag.py. Extending the conformance runner to also exercise argv-level invariants would require subprocess invocation and changes to the loader at src/amplifier_agent_lib/protocol/conformance/loader.py (engine-internal, off limits per the PR scope) and is intentionally left for a future PR.

Verification (host machine):

* wrappers/conformance/ (TS): 7 passed (was 5 after rename commit)

* wrappers/conformance/ (Py): 7 passed (was 5 after rename commit)

* tests/test_protocol_conformance_fixtures.py: 17 passed (was 16; the new fixtures load and validate)

* tests/test_phase_2_1_exit_gate.py: passes (now acknowledges the new fixtures in the sorted-name guard)

* Engine suite (uv run pytest -q --ignore=wrappers): 519 passed, 3 pre-existing failures in tests/cli/test_mode_a_v2_envelope.py (unchanged from PR #31's pre-existing baseline -- they reference the long-removed --mcp-servers flag and are tracked for a separate cleanup).

* Wrappers/python: 48 passed; wrappers/typescript: 63 passed; manual smoke confirms --host-capabilities / --env-allowlist / --env-extra / --allow-protocol-skew / --mcp-config-path all reject with click UsageError ('no such option').

---------

Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com>
manojp99 pushed a commit that referenced this pull request Jun 3, 2026
Engine version bump for the host-config-layer release window. Pairs with
the wire PROTOCOL_VERSION bump (0.2.0 -> 0.3.0) and consolidates argv/wire
surface removals shipped in PRs #27, #29, #30, #31.

Verified:
  $ uv run amplifier-agent --version
  amplifier-agent, version 0.4.0

BREAKING CHANGE: Engine version 0.3.0 -> 0.4.0. Wire protocol 0.2.0 -> 0.3.0
shipped in the same release. Old wrappers fail handshake. See CHANGELOG.md
for the full argv/wire/API removal list.
manojp99 pushed a commit that referenced this pull request Jun 3, 2026
Python wrapper version bump to pair with the engine 0.4.0 release.
Same major.minor as engine — the two move together.

The wrapper's compiled PROTOCOL_VERSION (sourced from amplifier_agent_lib)
follows the engine bump 0.2.0 -> 0.3.0 transitively.

BREAKING CHANGE: SpawnAgentParams API removed envAllowlist, envExtra,
allowProtocolSkew, host, and mcpConfigPath fields across PRs #27, #29, #31.
Callers must migrate to host_config (JSON file passed via --config or
$AMPLIFIER_AGENT_CONFIG) or env var injection (AMPLIFIER_MCP_CONFIG).
manojp99 pushed a commit that referenced this pull request Jun 3, 2026
The TS wrapper jumps minor (0.4.0 -> 0.5.0) rather than tracking the
engine's major.minor (0.4.0) because of release-window history:

  - 0.4.0 was already published to npm (verified: 'npm view
    amplifier-agent-ts versions' lists 0.3.0, 0.3.1, 0.4.0)
  - 0.4.0 was published by PR #17 (path-based MCP config delivery,
    pre-#27/#29/#30/#31)
  - Since the 0.4.0 publish, PRs #27, #29, #30, #31 have all landed,
    removing breaking surface from the TS wrapper API:
      * SpawnAgentParams.host / HostCapabilities type (#27)
      * mcpConfigPath field + argv emission (#29)
      * envAllowlist / envExtra / allowProtocolSkew fields (#31)

We cannot republish 0.4.0 with different code, and the accumulated changes
are breaking (not a patch). Bumping to 0.5.0 puts the next npm release on
a fresh, unpublished version. If you have context I'm missing about a
prior decision to keep TS major.minor tied to engine major.minor, override
with a follow-up bump.

BREAKING CHANGE: TS wrapper API removed SpawnAgentParams.host,
HostCapabilities type, InitializeHostParams type (#27); mcpConfigPath field
+ argv emission (#29); envAllowlist, envExtra, allowProtocolSkew fields
(#31). Callers must migrate to AMPLIFIER_MCP_CONFIG env var and a
host_config JSON file passed via --config.
manojp99 pushed a commit that referenced this pull request Jun 3, 2026
, #32)

Replace the [Unreleased] section with a full [0.4.0] - 2026-06-03 entry
that consolidates the host-config-layer release window:

  PR #27 - Host config layer + drop hostCapabilities surface
  PR #29 - Drop --mcp-config-path argv (subsumed by host config + env var)
  PR #30 - host-config skills: block + tool-skills bundle composition
  PR #31 - Drop env-allowlist, env-extra, allow-protocol-skew from wrappers
  PR #32 - Restore conformance suite

Highlights:
  - 4 argv flags + 1 env var removed (subsumed by host config layer)
  - hostCapabilities fully removed from envelope, initialize, and wrapper API
  - 5th host-config block 'skills:' (D11/D12/D13)
  - Wire protocol 0.2.0 -> 0.3.0 (BREAKING)
  - Engine 0.3.0 -> 0.4.0, Python wrapper 0.3.0 -> 0.4.0, TS wrapper 0.4.0 -> 0.5.0

Also documents the cross-repo follow-ups that downstream consumers
(notably amplifier-module-provider-nc) must catch up on but are NOT
part of this release.
manojp99 pushed a commit that referenced this pull request Jun 3, 2026
Closes the last 4 Python CI failures on this release branch.

(1) tests/cli/test_config_show.py::test_config_show_reports_default_when_env_absent

Click's CliRunner.invoke(env=...) MERGES the env dict with os.environ instead
of replacing it. GitHub Actions runners set XDG_CONFIG_HOME by default, which
leaked into the test and made source='env:XDG_CONFIG_HOME' instead of the
'default' the test was asserting. Now uses monkeypatch.delenv() to explicitly
remove XDG_CONFIG_HOME / XDG_CACHE_HOME / XDG_STATE_HOME before invoking.

(2) tests/cli/test_mode_a_v2_envelope.py

The three test_mcp_servers_* tests (inline_json_parsed, at_path_form,
malformed_json_yields_argv_envelope) target the --mcp-servers argv flag.
That flag was renamed to --mcp-config-path by PR #24 and then fully removed
by PR #29. The tests have been failing as 'pre-existing baseline' through
PRs #27, #29, #31, #32, and #33's earlier baselines. They test removed
surface and should never have been kept.

Replaced with an inline comment naming the removal context and pointing at
the removal guardrail at tests/cli/test_drop_mcp_config_path_flag.py.

Local: 532 passed, 3 skipped, 0 failed (full pytest tests/).
manojp99 added a commit that referenced this pull request Jun 3, 2026
…ce restored (#33)

* chore(protocol)!: bump wire PROTOCOL_VERSION 0.2.0 -> 0.3.0

Bump the wire protocol version to reflect accumulated backward-incompatible
changes shipped under the 0.4.0 release window:

  - metadata.hostCapabilities removed from response envelope (#27)
  - InitializeParams.host removed (#27)
  - InitializeParams.mcpServers renamed to mcpConfigPath (#24)
  - skills field added (host config skills: block, #30)

Old wrappers pinned to '0.2.0' should hard-fail handshake with a typed
protocol_version_mismatch error and exit 2 — verified manually:

    $ uv run amplifier-agent run --protocol-version 0.2.0 --session-id sm 'hi'
    {... "code": "protocol_version_mismatch" ...}
    EXIT=2

    $ uv run amplifier-agent run --protocol-version 0.3.0 --session-id sm 'hi'
    {... "reply": "..." ...}
    EXIT=0

Updated sites (audited via 'git grep "0.2.0" src/ tests/'):

  - src/amplifier_agent_lib/protocol/methods.py — PROTOCOL_VERSION constant
  - src/amplifier_agent_lib/protocol/spec.md — regenerated artifact
  - 9 conformance fixtures' protocolVersion: literals (setup + initialize params)
  - version_skew.yaml — serverVersion in expected error.data
  - 6 test files pinning protocolVersion in wrapper-side InitializeParams

Left as historical references (per release-issue guidance):

  - loader.py docstring example (illustrative fixture shape)
  - test_protocol_conformance_fixtures.py's self-contained _VALID_FIXTURE
    (loader smoke test, not engine-compat)
  - serverInfo.version: "0.2.0" in fixture script result blocks
    (not asserted by conformance harness — engine emits __version__ at
    runtime; fixture scripts are descriptive, only the explicit
    assertions: block is verified)

BREAKING CHANGE: Wire protocol 0.2.0 -> 0.3.0. Old wrappers pinned to 0.2.0
will hard-fail handshake with protocol_version_mismatch (exit 2). Reinstall
both engine and wrapper, or set allowProtocolSkew: true in host config.

* chore(engine)!: bump amplifier-agent version 0.3.0 -> 0.4.0

Engine version bump for the host-config-layer release window. Pairs with
the wire PROTOCOL_VERSION bump (0.2.0 -> 0.3.0) and consolidates argv/wire
surface removals shipped in PRs #27, #29, #30, #31.

Verified:
  $ uv run amplifier-agent --version
  amplifier-agent, version 0.4.0

BREAKING CHANGE: Engine version 0.3.0 -> 0.4.0. Wire protocol 0.2.0 -> 0.3.0
shipped in the same release. Old wrappers fail handshake. See CHANGELOG.md
for the full argv/wire/API removal list.

* chore(wrapper-py)!: bump Python wrapper version 0.3.0 -> 0.4.0

Python wrapper version bump to pair with the engine 0.4.0 release.
Same major.minor as engine — the two move together.

The wrapper's compiled PROTOCOL_VERSION (sourced from amplifier_agent_lib)
follows the engine bump 0.2.0 -> 0.3.0 transitively.

BREAKING CHANGE: SpawnAgentParams API removed envAllowlist, envExtra,
allowProtocolSkew, host, and mcpConfigPath fields across PRs #27, #29, #31.
Callers must migrate to host_config (JSON file passed via --config or
$AMPLIFIER_AGENT_CONFIG) or env var injection (AMPLIFIER_MCP_CONFIG).

* chore(wrapper-ts)!: bump amplifier-agent-ts version 0.4.0 -> 0.5.0

The TS wrapper jumps minor (0.4.0 -> 0.5.0) rather than tracking the
engine's major.minor (0.4.0) because of release-window history:

  - 0.4.0 was already published to npm (verified: 'npm view
    amplifier-agent-ts versions' lists 0.3.0, 0.3.1, 0.4.0)
  - 0.4.0 was published by PR #17 (path-based MCP config delivery,
    pre-#27/#29/#30/#31)
  - Since the 0.4.0 publish, PRs #27, #29, #30, #31 have all landed,
    removing breaking surface from the TS wrapper API:
      * SpawnAgentParams.host / HostCapabilities type (#27)
      * mcpConfigPath field + argv emission (#29)
      * envAllowlist / envExtra / allowProtocolSkew fields (#31)

We cannot republish 0.4.0 with different code, and the accumulated changes
are breaking (not a patch). Bumping to 0.5.0 puts the next npm release on
a fresh, unpublished version. If you have context I'm missing about a
prior decision to keep TS major.minor tied to engine major.minor, override
with a follow-up bump.

BREAKING CHANGE: TS wrapper API removed SpawnAgentParams.host,
HostCapabilities type, InitializeHostParams type (#27); mcpConfigPath field
+ argv emission (#29); envAllowlist, envExtra, allowProtocolSkew fields
(#31). Callers must migrate to AMPLIFIER_MCP_CONFIG env var and a
host_config JSON file passed via --config.

* docs(changelog): consolidate 0.4.0 release notes (PRs #27, #29, #30, #31, #32)

Replace the [Unreleased] section with a full [0.4.0] - 2026-06-03 entry
that consolidates the host-config-layer release window:

  PR #27 - Host config layer + drop hostCapabilities surface
  PR #29 - Drop --mcp-config-path argv (subsumed by host config + env var)
  PR #30 - host-config skills: block + tool-skills bundle composition
  PR #31 - Drop env-allowlist, env-extra, allow-protocol-skew from wrappers
  PR #32 - Restore conformance suite

Highlights:
  - 4 argv flags + 1 env var removed (subsumed by host config layer)
  - hostCapabilities fully removed from envelope, initialize, and wrapper API
  - 5th host-config block 'skills:' (D11/D12/D13)
  - Wire protocol 0.2.0 -> 0.3.0 (BREAKING)
  - Engine 0.3.0 -> 0.4.0, Python wrapper 0.3.0 -> 0.4.0, TS wrapper 0.4.0 -> 0.5.0

Also documents the cross-repo follow-ups that downstream consumers
(notably amplifier-module-provider-nc) must catch up on but are NOT
part of this release.

* fix(ci): commit uv.lock for deterministic dependency resolution

The CI workflow uses astral-sh/setup-uv@v3 with enable-cache: true, which
defaults to globbing **/uv.lock to compute the cache key. With uv.lock
gitignored, every CI run failed at the install step with:

  No matches found for glob **/uv.lock

Committing uv.lock fixes CI and aligns with Astral's recommended practice
for reproducible builds. Catches reproducibility drift between contributors
and CI/DTU. The lock is ~150KB.

This was a pre-existing CI break on main (every recent CI run failing) that
this version-bump release is unblocking as part of release-readiness.

* fix(ci): install Node + pnpm for conformance parity tests

tests/test_conformance_parity.py::test_ts_and_py_runners_agree[*] shells
out to 'pnpm exec tsx runner_ts.ts' to cross-validate the TS runner against
the Python runner. The Python CI job had no Node.js or pnpm installed, so
all 10 parametrized cases failed with:

  FileNotFoundError: [Errno 2] No such file or directory: 'pnpm'

Adds setup-node@v4, pnpm/action-setup@v3, and a pnpm-install step in
wrappers/conformance/ before pytest runs. Pre-existing CI gap that this
release branch is closing as part of release-readiness.

* fix(ci): make XDG test hermetic + delete obsolete --mcp-servers tests

Closes the last 4 Python CI failures on this release branch.

(1) tests/cli/test_config_show.py::test_config_show_reports_default_when_env_absent

Click's CliRunner.invoke(env=...) MERGES the env dict with os.environ instead
of replacing it. GitHub Actions runners set XDG_CONFIG_HOME by default, which
leaked into the test and made source='env:XDG_CONFIG_HOME' instead of the
'default' the test was asserting. Now uses monkeypatch.delenv() to explicitly
remove XDG_CONFIG_HOME / XDG_CACHE_HOME / XDG_STATE_HOME before invoking.

(2) tests/cli/test_mode_a_v2_envelope.py

The three test_mcp_servers_* tests (inline_json_parsed, at_path_form,
malformed_json_yields_argv_envelope) target the --mcp-servers argv flag.
That flag was renamed to --mcp-config-path by PR #24 and then fully removed
by PR #29. The tests have been failing as 'pre-existing baseline' through
PRs #27, #29, #31, #32, and #33's earlier baselines. They test removed
surface and should never have been kept.

Replaced with an inline comment naming the removal context and pointing at
the removal guardrail at tests/cli/test_drop_mcp_config_path_flag.py.

Local: 532 passed, 3 skipped, 0 failed (full pytest tests/).

---------

Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com>
manojp99 pushed a commit that referenced this pull request Jun 3, 2026
Mirrors PR #29 / #31 pattern: dist/ is tracked so consumers installing
from the git tarball get the compiled artifacts without a build step.

Regenerated from npm run build after issues #1, #2, #3, #4, #5, #6, #7,
#9, #10 landed.
manojp99 added a commit that referenced this pull request Jun 3, 2026
…, approval, getEngineInfo, +5 more) (#36)

* feat(wrapper-ts): re-export internal helpers from index.ts (#5)

Adds named re-exports from the package entry point so consumers can
import internal helpers without reaching into private deep paths:

  assembleArgv, AssembleArgvInput
  resolveMcpConfigPath, cleanupSpillFile, McpSpillResult
  buildEnv, resolveBinaryPath, probeEngineVersion,
    DEFAULT_ALLOWLIST, BLOCKED_ENV_KEYS,
    ResolveBinaryPathOptions, BuildEnvOptions
  Transport, TransportOptions, ExitInfo
  checkProtocolVersion, VersionCheckResult, VersionCheckOk,
    VersionCheckFail, CheckProtocolVersionOptions
  parseRunOutput, STDERR_TAIL_BYTES, SubprocessOutcome
  makeApprovalHandler, ApprovalAdapter, ApprovalRequest,
    ApprovalHandler

Each export is annotated @public.

Closes #5.

* feat(wrapper-ts): wire checkProtocolVersion() into init path (#9)

spawnAgent() now probes the engine's protocol version once during
initialization (via amplifier-agent version --json) and runs
checkProtocolVersion() against PROTOCOL_VERSION_REQUIRED_BY_WRAPPER
BEFORE constructing a SessionHandle. Mismatch fails fast wrapper-side
with AaaError(protocol_version_mismatch), saving a full subprocess
roundtrip later.

Adds two new SpawnAgentParams fields:
  - allowProtocolSkew?: boolean — bypass the check (mirrors engine's
    host_config.allowProtocolSkew)
  - _engineVersionProbe?: () => Promise<EngineVersionPayload> —
    test-only injection point for the probe

Also bumps PROTOCOL_VERSION_REQUIRED_BY_WRAPPER from "0.2.0" to
"0.3.0" to match the engine's current wire protocol
(amplifier_agent_lib.protocol.methods.PROTOCOL_VERSION). The wrapper
was shipping with a stale pin; the new check would have surfaced this
at startup.

Closes #9.

* feat(wrapper-ts): add runChildProcess injection point (#3)

Adds SpawnAgentParams.runChildProcess?: ChildProcessFactory — a public
seam to substitute the subprocess factory used inside SessionHandle.
When set, the wrapper invokes the factory in place of
child_process.spawn, preserving the same options shape (detached, stdio,
env, optional cwd).

Useful for:
  - Sandboxing (e.g. wrapping the child in a container or namespace)
  - Test doubles (e.g. EventEmitter fakes that drive scripted outputs)
  - Harness wrapping (e.g. observing the subprocess from outside)

ChildProcessFactory is exported as a @public type from index.ts.

Closes #3.

* feat(wrapper-ts)!: wire Transport NDJSON pipeline + dispatch to display.onEvent (#2, #4, #6)

The engine emits one JSON object per line on the child subprocess's
stderr stream for each wire-protocol notification (progress,
result/delta, result/final, thinking/delta, thinking/final,
tool/started, tool/completed, approval/request, approval/timeout,
plus wire-level error). Before this change the wrapper buffered
stderr as raw text and silently dropped every event — the existing
Transport class implemented NDJSON parsing but was never wired
anywhere (dead code).

This change:

  - Adds parseNdjsonStream(stream, {onJson, onNonJson?}) — a
    standalone helper extracted from the parsing logic Transport
    already had. Resolves when the stream emits 'close'. Exported
    @public.

  - Wires parseNdjsonStream onto child.stderr inside
    SessionHandle.makeIterable(). JSON lines are parsed into
    'notification' DisplayEvents and dispatched to
    params.display?.onEvent. Non-JSON lines (and JSON lines, for
    completeness) are still accumulated into stderrBuf so the
    stderrTail surface on parseRunOutput remains diagnostically
    useful.

  - Extends the DisplayEvent discriminated union with a new
    {type: 'notification', method: string, params: unknown}
    variant. **BREAKING**: existing exhaustive switch statements
    on event.type will no longer be exhaustive without a
    notification branch.

  - Threads SpawnAgentParams.display through to SessionHandle so
    the callback that was previously silently dropped is now
    actually fired (Issue #4).

Closes #2, #4, #6.

BREAKING CHANGE: display.onEvent callbacks are now actually invoked
with wire-event notifications. Callers that registered onEvent
expecting it to be a no-op may observe new event flow. The
DisplayEvent union has a new 'notification' variant; exhaustive
switch statements need a corresponding branch.

* feat(wrapper-ts): surface --config flag via SpawnAgentParams.configPath (#1)

Engine PR #27 / v0.4.0 added the --config <path> flag and the
host_config layer (approval mode, MCP servers, provider defaults,
allowProtocolSkew, etc.). The wrapper had no surface to forward this,
so callers had to fall back to AMPLIFIER_AGENT_CONFIG in env.extra.

This change:

  - Adds SpawnAgentParams.configPath?: string (public, @public TSDoc).
  - Adds AssembleArgvInput.configPath?: string.
  - assembleArgv emits --config <path> when configPath is set.
  - Threads configPath through SessionHandleParams to the per-submit
    argv assembly.

Also drive-by adds approvalMode field to AssembleArgvInput (used by
#10's commit). The argv-builder now reads input.approvalMode and emits
-y / -n / nothing accordingly. Default remains -y for backward compat
with callers that haven't opted into the approval API.

Closes #1.

* feat(wrapper-ts)!: wire approval API to engine -y/-n + approval.mode (#10)

Previously, SpawnAgentParams.approval threw AaaError(
approval_not_supported_in_v1) whenever set because it required the
mid-turn onRequest callback that v1 doesn't support.

This change extends SpawnAgentParams.approval to also accept the
static-policy shape { mode: 'yes' | 'no' | 'prompt' }, which maps to
engine argv:

  - 'yes'    -> -y (auto-allow every tool call)
  - 'no'     -> -n (auto-deny every tool call)
  - 'prompt' -> emit no flag; engine falls back to
                host_config.approval.mode or the bundle's TTY-based
                default. This is how a host hands policy resolution
                back to the engine.

The legacy { onRequest, timeoutMs } form still throws
approval_not_supported_in_v1 — the Mode A wire has no mid-turn
channel. Mid-turn callbacks will return when WG-4 lands.

Engine compatibility: { mode: 'prompt' } requires
amplifier-agent >= 0.4.0 (PR #34 added host_config.approval.mode).

Closes #10.

BREAKING CHANGE: SpawnAgentParams.approval is now a union shape;
callers passing { mode } no longer hit approval_not_supported_in_v1.
Callers that defensively catch that error need to remove the try/catch
when migrating to the mode shape.

* feat(wrapper-ts): implement getEngineInfo() — engineVersion + bundleDigest (#7)

Closes the Task-9 TODO: getEngineInfo() now returns the values
captured during the engine version probe that spawnAgent() runs at
init (Issue #9). Previously both fields were hardcoded empty strings.

  - engineVersion populated from `amplifier-agent version --json`
    payload's `version` field.
  - bundleDigest populated from the probe payload's optional
    `bundleDigest` field. The engine's current `version --json`
    output (from admin/version_info.py) only emits {version,
    protocolVersion} — bundleDigest will be empty string until a
    future engine release exposes it. Forward-compatible: when the
    engine adds it, the wrapper picks it up automatically with no
    further changes.

DONE_WITH_CONCERNS for the bundleDigest follow-up: filed as an
engine-side ask for a future PR. The wrapper does what it can with
the data the engine surface exposes today; the contract is wired
so the field will populate the moment the engine emits it.

Closes #7.

* chore(wrapper-ts): rebuild dist after hardening release changes

Mirrors PR #29 / #31 pattern: dist/ is tracked so consumers installing
from the git tarball get the compiled artifacts without a build step.

Regenerated from npm run build after issues #1, #2, #3, #4, #5, #6, #7,
#9, #10 landed.

* chore(release): bump amplifier-agent-ts to 0.6.0 + CHANGELOG

Wrapper hardening release closing 8 consumer-reported gaps at 0.5.0:
  #1  configPath surface
  #2  stderr NDJSON parsing
  #3  runChildProcess injection
  #4  display.onEvent dispatch
  #5  public re-exports
  #6  Transport dead code (root cause of #2/#4)
  #7  getEngineInfo() implementation
  #9  checkProtocolVersion() wired into init path
  #10 approval API mapped to engine -y/-n + approval.mode

Issue #8 in the consumer report was a misread — InitializeParams.
mcpConfigPath is intentionally retained in protocol-0.3.0. No
type change needed; the schema is canonical and correct.

This is a minor bump per 0.x convention even though some changes
are BREAKING — the wrapper hasn't shipped a 1.0 yet, so breaking
changes ride minor bumps. See CHANGELOG for the BREAKING list.

Engine compatibility: requires amplifier-agent >= 0.4.0.
Pinned protocol: 0.3.0.

---------

Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com>
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