Skip to content

Inject MAX_MCP_OUTPUT_TOKENS into AutoSkillit Order Sessions#910

Merged
Trecek merged 5 commits intointegrationfrom
inject-max-mcp-output-tokens-into-autoskillit-order-sessions/907
Apr 14, 2026
Merged

Inject MAX_MCP_OUTPUT_TOKENS into AutoSkillit Order Sessions#910
Trecek merged 5 commits intointegrationfrom
inject-max-mcp-output-tokens-into-autoskillit-order-sessions/907

Conversation

@Trecek
Copy link
Copy Markdown
Collaborator

@Trecek Trecek commented Apr 14, 2026

Summary

Claude Code v2.1.92 added a client-side MCP tool result size gate (default 25,000 tokens). The open_kitchen(name="implementation") response now exceeds this threshold (~80K chars / ~25-27K tokens), causing Claude Code to persist the result to a file and return an error instead — breaking orchestration flow.

The fix injects MAX_MCP_OUTPUT_TOKENS=50000 into every subprocess environment that AutoSkillit launches (headless sessions and cook sessions). Simultaneously, the variable is added to the denylist in _claude_env.py and to _HEADLESS_EXCLUSIVE_VARS in commands.py so it cannot leak from a parent session into children (children always get it set explicitly). A named constant _MAX_MCP_OUTPUT_TOKENS_VALUE = "50000" in commands.py avoids magic-number duplication and is re-exported via execution/__init__.py for use in _cook.py.

Architecture Impact

Security Diagram

%%{init: {'flowchart': {'nodeSpacing': 45, 'rankSpacing': 55, 'curve': 'basis'}}}%%
flowchart TB
    %% CLASS DEFINITIONS %%
    classDef cli fill:#1a237e,stroke:#7986cb,stroke-width:2px,color:#fff;
    classDef stateNode fill:#004d40,stroke:#4db6ac,stroke-width:2px,color:#fff;
    classDef handler fill:#e65100,stroke:#ffb74d,stroke-width:2px,color:#fff;
    classDef phase fill:#6a1b9a,stroke:#ba68c8,stroke-width:2px,color:#fff;
    classDef newComponent fill:#2e7d32,stroke:#81c784,stroke-width:2px,color:#fff;
    classDef output fill:#00695c,stroke:#4db6ac,stroke-width:2px,color:#fff;
    classDef detector fill:#b71c1c,stroke:#ef5350,stroke-width:2px,color:#fff;
    classDef gap fill:#ff6f00,stroke:#ffa726,stroke-width:2px,color:#000;
    classDef terminal fill:#1a237e,stroke:#7986cb,stroke-width:2px,color:#fff;

    %% ENTRY %%
    HOSTENV(["Host os.environ<br/>━━━━━━━━━━<br/>Untrusted / IDE-polluted"])

    subgraph DenylistLayer ["● TRUST BOUNDARY 1 — IDE Env Scrub (core/_claude_env.py)"]
        direction TB
        EXACTDENY["● IDE_ENV_DENYLIST<br/>━━━━━━━━━━<br/>Exact-match strip:<br/>CLAUDE_CODE_SSE_PORT<br/>ENABLE_IDE_INTEGRATION<br/>CLAUDE_CODE_WEBSOCKET_AUTH_FD<br/>VSCODE_GIT_ASKPASS_MAIN<br/>CURSOR_TRACE_ID · ZED_TERM<br/>EXIT_AFTER_STOP_DELAY ●<br/>SCENARIO_STEP_NAME ●<br/>MAX_MCP_OUTPUT_TOKENS ●"]
        PREFIXDENY["● IDE_ENV_PREFIX_DENYLIST<br/>━━━━━━━━━━<br/>Prefix-match strip:<br/>CLAUDE_CODE_IDE_*<br/>CLAUDE_CODE_SSE*"]
        AUTOCONN["● IDE_ENV_ALWAYS_EXTRAS<br/>━━━━━━━━━━<br/>Always injected:<br/>CLAUDE_CODE_AUTO_CONNECT_IDE=0<br/>(closes lock-file scan fallback)"]
    end

    subgraph ExclusiveFilter ["● TRUST BOUNDARY 2 — Headless Exclusive Var Filter (execution/commands.py)"]
        direction TB
        EXCL["● _HEADLESS_EXCLUSIVE_VARS filter<br/>━━━━━━━━━━<br/>Strips from os.environ before<br/>build_headless_cmd() base arg:<br/>EXIT_AFTER_STOP_DELAY<br/>SCENARIO_STEP_NAME<br/>MAX_MCP_OUTPUT_TOKENS"]
    end

    subgraph ExplicitInject ["● TRUST BOUNDARY 3 — Controlled Explicit Injection (execution/commands.py)"]
        direction TB
        MCPTOK["● MAX_MCP_OUTPUT_TOKENS=50000<br/>━━━━━━━━━━<br/>_MAX_MCP_OUTPUT_TOKENS_VALUE<br/>Always injected into headless extras<br/>Raises MCP gate: 25k → 50k tokens"]
        HEADLESSFLAGS["AUTOSKILLIT_HEADLESS=1<br/>━━━━━━━━━━<br/>Headless-mode signal<br/>Injected unconditionally"]
        OPTIONALS["Optional caller-controlled:<br/>━━━━━━━━━━<br/>EXIT_AFTER_STOP_DELAY (ms > 0)<br/>SCENARIO_STEP_NAME (non-empty)"]
    end

    subgraph SealedEnv ["SEALED ENV — MappingProxyType (core/_claude_env.py → build_claude_env)"]
        SEALED["MappingProxyType<br/>━━━━━━━━━━<br/>Read-only view<br/>Post-build mutation blocked"]
    end

    subgraph HeadlessPath ["● Headless Session Path (execution/commands.py → build_full_headless_cmd)"]
        HEADLESSCMD["● ClaudeHeadlessCmd<br/>━━━━━━━━━━<br/>cmd + sealed env<br/>Ready for subprocess runner"]
    end

    subgraph CookPath ["● Cook (Interactive) Session Path (cli/_cook.py)"]
        COOKEXTRAS["● env_extras injection<br/>━━━━━━━━━━<br/>MAX_MCP_OUTPUT_TOKENS=50000<br/>via _MAX_MCP_OUTPUT_TOKENS_VALUE<br/>(imported from execution/__init__.py ●)"]
        COOKCMD["ClaudeInteractiveCmd<br/>━━━━━━━━━━<br/>cmd + sealed env<br/>subprocess.run(env=spec.env)"]
    end

    BLOCKED(["BLOCKED<br/>━━━━━━━━━━<br/>IDE env vars<br/>Leaked session vars"])

    %% FLOW %%
    HOSTENV --> EXACTDENY
    HOSTENV --> PREFIXDENY
    EXACTDENY -->|"stripped"| BLOCKED
    PREFIXDENY -->|"stripped"| BLOCKED
    EXACTDENY -->|"surviving vars"| AUTOCONN
    PREFIXDENY -->|"surviving vars"| AUTOCONN

    AUTOCONN -->|"base env"| EXCL
    EXCL -->|"headless path"| MCPTOK
    EXCL -->|"headless path"| HEADLESSFLAGS
    EXCL -->|"headless path"| OPTIONALS

    MCPTOK --> SEALED
    HEADLESSFLAGS --> SEALED
    OPTIONALS --> SEALED
    AUTOCONN -->|"cook path"| COOKEXTRAS

    SEALED --> HEADLESSCMD
    COOKEXTRAS --> COOKCMD

    %% CLASS ASSIGNMENTS %%
    class HOSTENV cli;
    class EXACTDENY,PREFIXDENY detector;
    class AUTOCONN,EXCL detector;
    class MCPTOK,HEADLESSFLAGS phase;
    class OPTIONALS stateNode;
    class SEALED output;
    class HEADLESSCMD,COOKCMD output;
    class COOKEXTRAS phase;
    class BLOCKED gap;
Loading

Process Flow Diagram

%%{init: {'flowchart': {'nodeSpacing': 45, 'rankSpacing': 55, 'curve': 'basis'}}}%%
flowchart TB
    %% CLASS DEFINITIONS %%
    classDef terminal fill:#1a237e,stroke:#7986cb,stroke-width:2px,color:#fff;
    classDef stateNode fill:#004d40,stroke:#4db6ac,stroke-width:2px,color:#fff;
    classDef handler fill:#e65100,stroke:#ffb74d,stroke-width:2px,color:#fff;
    classDef phase fill:#6a1b9a,stroke:#ba68c8,stroke-width:2px,color:#fff;
    classDef detector fill:#b71c1c,stroke:#ef5350,stroke-width:2px,color:#fff;
    classDef output fill:#00695c,stroke:#4db6ac,stroke-width:2px,color:#fff;

    %% TERMINALS %%
    START([START])
    DONE([DONE — ClaudeHeadlessCmd / ClaudeInteractiveCmd])

    %% ── ENTRY SPLIT ─────────────────────────────────────────── %%
    ENTRY{"Session<br/>type?"}

    START --> ENTRY

    %% ══════════════════════════════════════════════════════════ %%
    %%  HEADLESS PATH                                            %%
    %% ══════════════════════════════════════════════════════════ %%
    subgraph HeadlessPath ["Headless Session Path  (execution/commands.py ●)"]
        direction TB

        BFH["● build_full_headless_cmd()<br/>━━━━━━━━━━<br/>Entry: skill_command, cwd,<br/>completion_marker, model, plugin_dir,<br/>exit_after_stop_delay_ms, scenario_step_name"]

        FILTER["● Filter os.environ<br/>━━━━━━━━━━<br/>Remove _HEADLESS_EXCLUSIVE_VARS:<br/>CLAUDE_CODE_EXIT_AFTER_STOP_DELAY<br/>SCENARIO_STEP_NAME<br/>MAX_MCP_OUTPUT_TOKENS<br/>→ filtered_base"]

        EXTRAS_H["● Assemble headless extras<br/>━━━━━━━━━━<br/>AUTOSKILLIT_HEADLESS = 1<br/>MAX_MCP_OUTPUT_TOKENS = 50000  ← new<br/>+ conditional vars below"]

        OPT_DELAY{"exit_after_stop<br/>_delay_ms > 0?"}
        OPT_STEP{"scenario_step<br/>_name set?"}

        INJECT_DELAY["Add CLAUDE_CODE_EXIT_AFTER_STOP_DELAY"]
        INJECT_STEP["Add SCENARIO_STEP_NAME"]

        PROMPT["Build prompt string<br/>━━━━━━━━━━<br/>_ensure_skill_prefix()<br/>→ _inject_completion_directive()<br/>→ _inject_cwd_anchor()<br/>→ _inject_narration_suppression()"]

        BHC["build_headless_cmd()<br/>━━━━━━━━━━<br/>cmd: [claude, --print, prompt,<br/>--dangerously-skip-permissions, ...]<br/>env: build_claude_env(base=filtered_base,<br/>                      extras=extras)"]
    end

    %% ══════════════════════════════════════════════════════════ %%
    %%  COOK (INTERACTIVE) PATH                                  %%
    %% ══════════════════════════════════════════════════════════ %%
    subgraph CookPath ["Cook (Interactive) Session Path  (cli/_cook.py ●)"]
        direction TB

        COOK["● cook()<br/>━━━━━━━━━━<br/>User-facing session launcher<br/>Imports _MAX_MCP_OUTPUT_TOKENS_VALUE<br/>from autoskillit.execution ●"]

        EXTRAS_C["● Assemble cook extras<br/>━━━━━━━━━━<br/>MAX_MCP_OUTPUT_TOKENS = 50000  ← new<br/>passed as env_extras=..."]

        BIC["build_interactive_cmd()<br/>━━━━━━━━━━<br/>cmd: [claude, --dangerously-skip-permissions,<br/>      --plugin-dir, --add-dir, ...]<br/>env: build_claude_env(extras=env_extras)"]
    end

    %% ══════════════════════════════════════════════════════════ %%
    %%  SHARED ENV BUILD LAYER  (_claude_env.py ●)              %%
    %% ══════════════════════════════════════════════════════════ %%
    subgraph EnvBuild ["● build_claude_env()  (core/_claude_env.py ●)"]
        direction TB

        SRC{"base provided?"}
        USE_BASE["Use provided base<br/>(filtered_base for headless)"]
        USE_OSENV["Use os.environ<br/>(cook path)"]

        SCRUB["● Denylist scrub loop<br/>━━━━━━━━━━<br/>For each key in src:<br/>  reject if key ∈ IDE_ENV_DENYLIST  ← extended<br/>  reject if key starts with prefix in<br/>  IDE_ENV_PREFIX_DENYLIST"]

        DENYLIST_NOTE["IDE_ENV_DENYLIST now includes:<br/>━━━━━━━━━━<br/>MAX_MCP_OUTPUT_TOKENS  ← new<br/>CLAUDE_CODE_EXIT_AFTER_STOP_DELAY  ← new<br/>SCENARIO_STEP_NAME  ← new<br/>+ original IDE vars"]

        ALWAYS["Inject IDE_ENV_ALWAYS_EXTRAS<br/>━━━━━━━━━━<br/>CLAUDE_CODE_AUTO_CONNECT_IDE = 0"]

        MERGE_EXTRAS["Merge caller extras<br/>━━━━━━━━━━<br/>Including MAX_MCP_OUTPUT_TOKENS = 50000<br/>(always wins — injected after scrub)"]

        SEAL["Return MappingProxyType<br/>━━━━━━━━━━<br/>Read-only sealed env<br/>prevents post-build mutation"]
    end

    %% ══════════════════════════════════════════════════════════ %%
    %%  RE-EXPORT BRIDGE  (execution/__init__.py ●)             %%
    %% ══════════════════════════════════════════════════════════ %%
    REEXPORT["● execution/__init__.py<br/>━━━━━━━━━━<br/>Re-exports _MAX_MCP_OUTPUT_TOKENS_VALUE<br/>from commands.py<br/>(avoids submodule import in _cook.py)"]

    %% ── FLOW ─────────────────────────────────────────────────── %%

    ENTRY -->|"headless"| BFH
    ENTRY -->|"cook / interactive"| COOK

    BFH --> FILTER
    FILTER --> PROMPT
    FILTER --> EXTRAS_H
    EXTRAS_H --> OPT_DELAY
    OPT_DELAY -->|"yes"| INJECT_DELAY
    OPT_DELAY -->|"no"| OPT_STEP
    INJECT_DELAY --> OPT_STEP
    OPT_STEP -->|"yes"| INJECT_STEP
    OPT_STEP -->|"no"| BHC
    INJECT_STEP --> BHC
    PROMPT --> BHC

    COOK --> REEXPORT
    REEXPORT -->|"_MAX_MCP_OUTPUT_TOKENS_VALUE"| EXTRAS_C
    COOK --> EXTRAS_C
    EXTRAS_C --> BIC

    BHC --> SRC
    BIC --> SRC

    SRC -->|"yes (headless)"| USE_BASE
    SRC -->|"no (cook)"| USE_OSENV
    USE_BASE --> SCRUB
    USE_OSENV --> SCRUB
    DENYLIST_NOTE -.->|"defines"| SCRUB
    SCRUB --> ALWAYS
    ALWAYS --> MERGE_EXTRAS
    MERGE_EXTRAS --> SEAL

    SEAL --> DONE

    %% ── CLASS ASSIGNMENTS ────────────────────────────────────── %%
    class START,DONE terminal;
    class ENTRY,OPT_DELAY,OPT_STEP,SRC stateNode;
    class BFH,BHC,BIC,COOK,PROMPT handler;
    class FILTER,EXTRAS_H,EXTRAS_C,REEXPORT phase;
    class SCRUB,DENYLIST_NOTE detector;
    class INJECT_DELAY,INJECT_STEP,ALWAYS,MERGE_EXTRAS,USE_BASE,USE_OSENV,SEAL output;
Loading

Module Dependency Diagram

%%{init: {'flowchart': {'nodeSpacing': 50, 'rankSpacing': 70, 'curve': 'basis'}}}%%
graph TB
    %% CLASS DEFINITIONS %%
    classDef cli fill:#1a237e,stroke:#7986cb,stroke-width:2px,color:#fff;
    classDef stateNode fill:#004d40,stroke:#4db6ac,stroke-width:2px,color:#fff;
    classDef handler fill:#e65100,stroke:#ffb74d,stroke-width:2px,color:#fff;
    classDef phase fill:#6a1b9a,stroke:#ba68c8,stroke-width:2px,color:#fff;
    classDef integration fill:#c62828,stroke:#ef9a9a,stroke-width:2px,color:#fff;
    classDef output fill:#00695c,stroke:#4db6ac,stroke-width:2px,color:#fff;

    subgraph LayerCLI ["L3 — CLI LAYER"]
        direction LR
        COOK["● cli/_cook.py<br/>━━━━━━━━━━<br/>cook(): interactive skill launcher<br/>Imports _MAX_MCP_OUTPUT_TOKENS_VALUE<br/>Passes as env_extras to build_interactive_cmd"]
    end

    subgraph LayerExec ["L1 — EXECUTION LAYER"]
        direction LR
        EXEC_INIT["● execution/__init__.py<br/>━━━━━━━━━━<br/>Re-exports _MAX_MCP_OUTPUT_TOKENS_VALUE<br/>so cli/ avoids submodule import"]
        COMMANDS["● execution/commands.py<br/>━━━━━━━━━━<br/>_MAX_MCP_OUTPUT_TOKENS_VALUE = '50000'<br/>_HEADLESS_EXCLUSIVE_VARS (frozenset)<br/>build_full_headless_cmd(): injects token limit<br/>build_interactive_cmd(): caller-supplied extras<br/>build_headless_cmd(): delegates to build_claude_env"]
    end

    subgraph LayerCore ["L0 — CORE LAYER"]
        direction LR
        CLAUDE_ENV["● core/_claude_env.py<br/>━━━━━━━━━━<br/>IDE_ENV_DENYLIST: strips MAX_MCP_OUTPUT_TOKENS<br/>IDE_ENV_PREFIX_DENYLIST<br/>IDE_ENV_ALWAYS_EXTRAS<br/>build_claude_env(): scrub + seal env"]
        CORE_INIT["core/__init__.py<br/>━━━━━━━━━━<br/>Re-exports build_claude_env<br/>for execution layer consumers"]
    end

    subgraph LayerExt ["EXTERNAL"]
        direction LR
        OS_ENVIRON["os.environ<br/>━━━━━━━━━━<br/>Host process environment<br/>(MAX_MCP_OUTPUT_TOKENS stripped<br/>by denylist before child launch)"]
        CLAUDE_PROC["claude subprocess<br/>━━━━━━━━━━<br/>Receives sealed env<br/>MAX_MCP_OUTPUT_TOKENS=50000<br/>CLAUDE_CODE_AUTO_CONNECT_IDE=0"]
    end

    %% VALID DEPENDENCIES (downward) %%
    COOK -->|"from autoskillit.execution import<br/>_MAX_MCP_OUTPUT_TOKENS_VALUE,<br/>build_interactive_cmd"| EXEC_INIT
    EXEC_INIT -->|"re-exports from"| COMMANDS
    COMMANDS -->|"from autoskillit.core import<br/>build_claude_env, ClaudeFlags,<br/>ValidatedAddDir, temp_dir_display_str"| CORE_INIT
    CORE_INIT -->|"re-exports from"| CLAUDE_ENV

    %% DATA FLOW %%
    OS_ENVIRON -->|"base env (filtered:<br/>_HEADLESS_EXCLUSIVE_VARS removed)"| COMMANDS
    CLAUDE_ENV -->|"MappingProxyType<br/>scrubbed + sealed"| COMMANDS
    COMMANDS -->|"ClaudeHeadlessCmd / ClaudeInteractiveCmd<br/>(cmd=[], env=sealed)"| COOK
    COOK -->|"subprocess.run(cmd, env=spec.env)"| CLAUDE_PROC

    %% DESIGN INVARIANTS %%
    NOTE1["Design Invariant<br/>━━━━━━━━━━<br/>MAX_MCP_OUTPUT_TOKENS in denylist →<br/>cannot leak from host env into child.<br/>Injected only via explicit extras."]

    %% CLASS ASSIGNMENTS %%
    class COOK cli;
    class EXEC_INIT,COMMANDS handler;
    class CLAUDE_ENV,CORE_INIT stateNode;
    class OS_ENVIRON integration;
    class CLAUDE_PROC output;
    class NOTE1 phase;
Loading

Closes #907

Implementation Plan

Plan file: /home/talon/projects/autoskillit-runs/impl-20260414-065641-276152/.autoskillit/temp/make-plan/inject_max_mcp_output_tokens_plan_2026-04-14_070000.md

🤖 Generated with Claude Code via AutoSkillit

Token Usage Summary

Step uncached output cache_read cache_write count time
plan 157 11.3k 787.5k 62.7k 1 3m 0s
verify 2.2k 9.5k 397.5k 52.3k 1 2m 38s
implement 2.3k 9.3k 1.4M 55.3k 1 2m 53s
fix 182 6.9k 754.3k 31.9k 1 10m 4s
prepare_pr 60 5.7k 181.0k 24.0k 1 1m 47s
run_arch_lenses 210 16.3k 654.8k 88.8k 3 5m 3s
compose_pr 59 7.9k 198.8k 30.6k 1 1m 59s
Total 5.2k 66.9k 4.4M 345.6k 27m 27s

Trecek and others added 3 commits April 14, 2026 07:06
Raises the Claude Code client-side MCP tool result size gate from 25K
to 50K tokens in every AutoSkillit-launched session, preventing
open_kitchen() responses (~27K tokens) from being persisted to a file
instead of returned inline.

- Add MAX_MCP_OUTPUT_TOKENS to IDE_ENV_DENYLIST in core/_claude_env.py
- Add _MAX_MCP_OUTPUT_TOKENS_VALUE constant and extend
  _HEADLESS_EXCLUSIVE_VARS in execution/commands.py
- Inject the constant into build_full_headless_cmd extras dict
- Pass env_extras carrying the constant in cli/_cook.py cook()
- Add tests for denylist coverage, headless injection, exclusive-var
  stripping, and cook session injection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator Author

@Trecek Trecek left a comment

Choose a reason for hiding this comment

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

AutoSkillit PR Review — Verdict: changes_requested (5 actionable findings)

Comment thread tests/cli/test_cook_env_scrub.py Outdated
Comment thread tests/execution/test_commands.py Outdated
Comment thread tests/execution/test_commands.py Outdated
# Raises the Claude Code client-side MCP tool result size gate from the
# default 25,000 tokens to 50,000, preventing open_kitchen() responses
# from being persisted to a file instead of returned inline.
_MAX_MCP_OUTPUT_TOKENS_VALUE: str = "50000"
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

[warning] defense/cohesion: _MAX_MCP_OUTPUT_TOKENS_VALUE is underscore-prefixed (private) but intentionally re-exported via execution/__init__.py. Consider removing the leading underscore to match its public surface contract (MAX_MCP_OUTPUT_TOKENS_VALUE).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Valid observation — flagged for design decision. The underscore prefix is consistent with other module-private-but-re-exported symbols in execution/__init__.py (e.g. _execute_readonly_query, _refresh_quota_cache). Renaming would touch 5 locations. Deferring to a separate refactor.

Comment thread src/autoskillit/execution/__init__.py Outdated
Trecek added 2 commits April 14, 2026 07:45
…OKENS_VALUE re-export

The inline comment named _cook.py as the sole consumer, embedding coupling
rationale into the re-export layer. The noqa: F401 alone is sufficient to
signal re-export intent.
…assertions

Replaced hardcoded "50000" literals with the imported constant in
test_cook_env_scrub.py and test_commands.py so that a value change
in the constant is automatically caught by these tests.
@Trecek Trecek added this pull request to the merge queue Apr 14, 2026
Merged via the queue into integration with commit eb05c58 Apr 14, 2026
2 checks passed
@Trecek Trecek deleted the inject-max-mcp-output-tokens-into-autoskillit-order-sessions/907 branch April 14, 2026 15:00
github-merge-queue bot pushed a commit that referenced this pull request Apr 14, 2026
…ypes (#922)

## Summary

`build_interactive_cmd()` is a pure pass-through for environment
variables — it forwards caller-supplied `env_extras` to
`build_claude_env` without injecting any defaults. This is structurally
asymmetric with `build_full_headless_cmd()`, which internally injects
`MAX_MCP_OUTPUT_TOKENS=50000` and `AUTOSKILLIT_HEADLESS=1` before
delegating. The asymmetry means interactive launch paths depend on
caller discipline to inject required vars, and when
`_launch_cook_session` (the `order` command's launch path) was never
updated by PR #910, the gap went undetected.

The fix adds a `_SESSION_BASELINE_ENV` frozen mapping in `commands.py`
that `build_interactive_cmd` and `build_headless_resume_cmd` merge as
defaults. Removes redundant caller-side injection from `_cook.py`. Adds
structural guard tests covering all three session builders.

Closes #916

## Implementation Plan

Plan file:
`/home/talon/projects/autoskillit-runs/remediation-20260414-084428-773530/.autoskillit/temp/rectify/rectify_max_mcp_output_tokens_interactive_gap_2026-04-14_090500.md`

🤖 Generated with [Claude Code](https://claude.com/claude-code) via
AutoSkillit

## Token Usage Summary

| Step | uncached | output | cache_read | cache_write | count | time |
|------|----------|--------|------------|-------------|-------|------|
| investigate | 2.6k | 8.3k | 628.8k | 48.1k | 1 | 4m 55s |
| rectify | 4.1k | 26.1k | 1.8M | 161.5k | 3 | 12m 42s |
| dry_walkthrough | 3.2k | 10.1k | 1.2M | 78.6k | 1 | 4m 39s |
| implement | 77 | 10.5k | 1.6M | 54.7k | 1 | 4m 19s |
| prepare_pr | 30 | 4.5k | 374.0k | 34.2k | 1 | 1m 34s |
| run_arch_lenses | 49 | 8.2k | 538.5k | 47.7k | 1 | 2m 52s |
| compose_pr | 23 | 1.5k | 128.6k | 15.6k | 1 | 39s |
| **Total** | 10.1k | 69.2k | 6.3M | 440.6k | | 31m 42s |

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.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