feat(mcp/ocs): add file_path mode to ocs_upload_collection_files (close Phase 5 b64 wedge)#360
Open
jjackson wants to merge 1 commit into
Open
feat(mcp/ocs): add file_path mode to ocs_upload_collection_files (close Phase 5 b64 wedge)#360jjackson wants to merge 1 commit into
jjackson wants to merge 1 commit into
Conversation
Two consecutive Phase 5 (ocs-setup) dispatches on leep-paint-collection
hit stream-idle timeouts (~30 min / 49 calls + ~114 min / 44 calls)
without writing any Drive artifacts. Session-log bisect pinned the
cause: the agent base64-encoded its ~67 KB RAG content pack on disk,
then `Read` the .b64 chunks back into context to emit them as the
`content` field of the tool_use input. Generating 100s of KB of b64 as
output tokens stalled model generation either mid-emit or on the next
turn. Pure output-token budget exhaustion — no OCS slowness, no auth
churn, no QA loop, no indexing wedge.
Fix: extend `ocs_upload_collection_files` to accept `file_path` per
file. MCP reads the bytes server-side via fs/promises and b64-encodes
internally — agent never holds the encoded form. Each file MUST supply
EXACTLY ONE of `content` (legacy inline b64) or `file_path` (absolute
filesystem path); mixed or missing sources fail fast with a named
error citing the offending file.
Refactor: file-decoding logic moved into `decodeUploadCollectionFileSource`,
exported from mcp/ocs-server.ts for unit-testability.
7 new vitest cases in test/mcp/ocs/unit/upload-collection-files-decoder.test.ts:
- file_path reads UTF-8 text verbatim
- file_path reads arbitrary binary verbatim
- content decodes inline b64 (legacy preserved)
- missing source → named error
- both sources → named error
- error message names offending file (debuggability)
- ENOENT propagates cleanly
docs/learnings/2026-05-19-ocs-upload-b64-context-wedge.md documents the
bug, the four prior-framing refutations, the session-log proof, the
generalized class ("MCP atom accepts large payload as string param")
and the audit candidates that still need the same fix
(drive_upload_binary, drive_create_file, drive_update_file).
docs/learnings/2026-05-12-boundary-probe-registry.md updated with the
new Shipped probe + a generalized pending probe row.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two consecutive
ace:ocs-setupdispatches onleep-paint-collection/20260517-1515hit stream-idle timeouts (~30 min / 49 calls + ~114 min / 44 calls) without writing any Drive artifacts. Session-log bisect pinned the cause: agent base64-encoded its ~67 KB RAG content pack on disk, thenReadthe .b64 chunks back into its own context to emit them as thecontentfield of theocs_upload_collection_filestool_use input. Generating 100s of KB of b64 as output tokens stalls model generation either mid-emit or on the next turn. Pure output-token budget exhaustion — no OCS slowness, no auth churn, no QA loop, no indexing wedge.Fix
mcp/ocs-server.ts—ocs_upload_collection_filesextended to acceptfile_pathas an alternative source per file. The MCP reads the file server-side viafs/promisesand b64-encodes internally. The agent never holds the encoded form in its context. Exactly-one-source-per-file invariant enforced server-side: each file MUST supply EXACTLY ONE ofcontent(legacy inline b64) orfile_path(absolute filesystem path); mixed or missing sources fail fast with a named error citing the offending file.Refactor: file-decoding logic moved into
decodeUploadCollectionFileSource, exported frommcp/ocs-server.tsfor unit-testability.Tests
7 new vitest cases in
test/mcp/ocs/unit/upload-collection-files-decoder.test.ts:All 12 tests in test/mcp/ocs pass.
tsc --noEmitclean.Skill-side guidance
Phase 5
ocs-content-packand any future skill calling this atom SHOULD usefile_pathfor any payload > ~1KB. Pattern:DO NOT
Readthe .b64 files. DO NOTReadthe original markdown files into context if all you're going to do is re-emit them through the upload tool — that's the wedge.Docs
docs/learnings/2026-05-19-ocs-upload-b64-context-wedge.md— full bug doc with prior-framing refutations (RAG indexing wedge, per-prompt QA loop, auth churn, OCS slowness — all wrong) and the session-log proof from both subagent transcripts.docs/learnings/2026-05-12-boundary-probe-registry.md— new Shipped probe row + a generalized pending probe ("every MCP atom whose input schema takes astringcarrying > ~10KB of payload should have a_pathcompanion"). Existing examples of the pattern done correctly:commcare_upload_multimedia.file_bytes_path,commcare_patch_xform.new_xform_xml_path. Still missing:drive_upload_binary.content,drive_create_file.content(high-value follow-ups).Recovery for
leep-paint-collection/20260517-1515After this PR merges +
/ace:update:experiment_id=12193, name "ACE - leep-paint-collection (run 20260517-1515)") viaocs_delete_chatbot— clean restart.file_pathmode (the new SKILL.md guidance ships in this PR; existingocs-content-packSKILL.md should be updated in a follow-up PR to bake the pattern in unconditionally).Test plan
npx vitest run test/mcp/ocs/— 12 passnpx tsc --noEmit— clean/ace:update, re-run Phase 5 of leep-paint-collection/20260517-1515 using file_path mode and confirm completion in expected wall time.skills/ocs-content-pack/SKILL.mdto mandate file_path mode for any payload > 1KB.🤖 Generated with Claude Code