A session id is the host's to supply, so the model is no longer shown one (comms-tg70) - #214
Merged
Merged
Conversation
… one (comms-tg70) docs/agent-experience.md principle 1: a human does not type their session id into the compose box. `session_id` was declared on seven tool schemas, so the model saw a parameter it has no way to fill — the value comes from Claude Code's PreToolUse hook, or from a non-CC host that stamps it into `arguments` itself. Neither route ever needed it advertised. What the tool ADVERTISES and what it ACCEPTS are now separate. `hostSuppliedArgs` names the arguments a host stamps in out of band; the guard in `registerTools` admits `properties ∪ hostSuppliedArgs` while the unknown-argument error still names only the advertised ones — an error listing `session_id` as valid would put the parameter back on the surface this removes it from. The relaxation is per-tool: a tool listing nothing still rejects `session_id`, and every tool still rejects everything else. Every supply channel is untouched. The boot-env feeder, the hook injection, and `readSessionId`'s read-back all work as before, which the existing tools-session suite proves — those tests pass `session_id` in `arguments` and assert the mint, and they are now tests of an undeclared argument being read. Seven tools carry it, not the five in the hook matcher: subscribe and unsubscribe are the identity route for a listen-first non-CC seat, and a host stamping the argument on a tool CC never stamps must not be told it is unknown. The instructions block goes too. `COMMY_INSTRUCTIONS` is injected into every agent's context verbatim, and it told the model to pass its conversation's session id. Removing the schema property while leaving that paragraph would have shipped a surface that instructs the model to send an argument no tool advertises. The contract a non-CC host implements now lives only in docs/self-hosting.md, which its operator reads. The manifest test asserts the same rule one seam over: a tool whose adapter path reaches `boundHttp` must RECEIVE `session_id`, not declare it. That rule is traced from a source scan, and a scan that stops matching satisfies every "no tool violates this" assertion by looking at nothing — so the receiving set is pinned at seven, and the advertise side is traced separately and asserted empty. Verified by mutation: renaming the marker fails the pin, and returning a `session_id` property to a schema fails the advertise-side rule.
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.
session_idwas declared on seven tool schemas, sotools/listshowed themodel a parameter it has no way to fill. The value comes from Claude Code's
PreToolUse hook, or from a non-CC host that stamps it into
argumentsitself —neither route ever needed it advertised. A human does not type their session id
into the compose box (
docs/agent-experience.mdprinciple 1).This is an encoding subtraction, not a supply deletion. Every channel that
binds an identity still binds one.
What the tool advertises and what it accepts are now separate
ToolDef.hostSuppliedArgsnames the arguments a host stamps in out of band.The guard in
registerToolsadmitsproperties ∪ hostSuppliedArgs, while theunknown-argument error still names only the advertised ones — an error reading
"Valid arguments: …, session_id" would put the parameter back on the surface
this removes it from.
The relaxation is per-tool, not a hole in the check: a tool listing nothing
still rejects
session_id, and every tool still rejects everything else.Seven tools carry it, not the five in the hook matcher.
subscribeandunsubscribeare the identity route for a listen-first non-CC seat, and a hoststamping the argument on a tool CC never stamps must not be told it is unknown.
An eighth site: the instructions block
This one is past the seven schemas, and is called out deliberately.
COMMY_INSTRUCTIONSinpackages/mcp/mcp-server.tsis the MCPinstructions:field — injected into every connected agent's context verbatim. It carried a
**session_id.**paragraph telling the model: "Pass your conversation'ssession id as the optional argument on
post,edit_message,react,unreact, andcurrent_identity."That is the agent-visible surface in prose, and principle 1 reaches it for the
same reason it reaches the schema. Removing the property while leaving the
paragraph would ship a self-contradictory build:
tools/listno longeradvertises the argument, and the instructions still tell the model to send it.
Same subtraction, second encoding.
It is a clean revert if it should be split out —
packages/mcp/mcp-server.tsplus its test in
packages/mcp/mcp-server.test.ts, nothing else depends on it.The contract a non-CC host implements now lives in
docs/self-hosting.md,which its operator reads: the seven accepting tools, the fact that the argument
is deliberately not advertised, and the UUID-or-unbound-stub rule.
The manifest test asserts the rule one seam over
hooks-manifest.test.tsheld that a tool whose adapter path reachesboundHttpmust DECLAREsession_id. Nothing declares one now, so the rule isrestated as RECEIVE and traced from the accept-side marker instead. The
substance is unchanged — the id still has to reach the tool.
That rule comes from a source scan, and a scan that stops matching satisfies
every "no tool violates this" assertion by looking at nothing. So the receiving
set is pinned at exactly seven, and the advertise side is traced separately and
asserted empty. Verified by mutation, not by inspection: renaming the marker
fails the pin, and returning a
session_idproperty to a schema fails theadvertise-side rule. Without the pin, the first mutation went silently green.
Supply is proven by the tests that were already there
The
tools-sessionsuite passessession_idinargumentsand asserts themint. Those are now tests of an undeclared argument being read, and they would
fail loudly if the guard rejected it. Three new ones state the property
directly: the argument is accepted where no schema advertises it, a tool that
takes none still rejects it, and a genuinely unknown argument is still rejected
alongside it.
Closes comms-tg70.