Repository navigation
Conversation
Entry validation (internal/entry/validate.go) requires session_id, branch, and commit for tasks, decisions, and learnings unless .ctxrc relaxes them, and section for tasks. extract.Opts reads all of them from the MCP arguments, but EntryAttrProps never declared the provenance fields, and the ctx_watch_update schema declared neither section nor priority. MCP clients only send what a tool schema advertises, so every ctx_add and ctx_watch_update call for those entry types failed with "missing required fields: --session-id, --branch, --commit" (ActiveMemory#190). Declare section, priority, session_id, branch, and commit in EntryAttrProps, so both entry tools take them from one definition, and test that both schemas advertise every field validation can require. Spec: specs/fix-mcp-add-provenance.md Signed-off-by: Ersan Bilik <ersanbilik@gmail.com>
Only the client knows its session ID, but the server can read branch and commit itself, and its values beat relayed ones: read at write time (a relayed commit predates any commit made since the prompt) and never retyped by a model. ctx_add and ctx_watch_update now fill branch and commit when the caller leaves them empty or "unknown", with the git calls the hook relay makes in provenance.Emit, falling back to "unknown" as it does, so MCP-written provenance matches the CLI path. An explicit value still wins, for an agent working in another checkout. session_id stays caller-supplied and required. Its description points the agent at the Session value ctx relays, or an explicit "unknown" when it has none, and the decision and learning prompts ask for it: their "all fields above" footers never listed it. Spec: specs/fix-mcp-add-provenance.md Signed-off-by: Ersan Bilik <ersanbilik@gmail.com>
SanitizedOpts promised sanitization for every text field but passed priority, section, branch, and commit through raw. format.Task writes priority, branch, and commit into the task line, and an unmatched section becomes a new "### " heading, so a line break in any of them forged task lines or headings in TASKS.md. Advertising branch and commit makes schema-driven clients send them. sanitize.Line removes every control character, including the tab and line breaks that StripControl keeps for multi-line content, and the Unicode line and paragraph separators, then truncates on a rune boundary. SanitizedOpts applies it to the four fields with a new MaxOptsLineLen (256). Over-long values are truncated, not rejected, as session IDs already are: this is the length cap that specs/sanitize-hardening-followup.md deferred for these fields. Spec: specs/fix-mcp-add-provenance.md Signed-off-by: Ersan Bilik <ersanbilik@gmail.com>
docs/cli/mcp.md listed neither section nor the provenance arguments for ctx_add, and ctx_watch_update also lacked priority and section, although validation requires section for tasks and session_id for tasks, decisions, and learnings. Both tables now list every argument the tools advertise, with a note on what to pass for session_id and when branch and commit come from git. The provenance_required rows in the configuration reference now say how each key applies to the MCP entry tools. Spec: specs/fix-mcp-add-provenance.md Signed-off-by: Ersan Bilik <ersanbilik@gmail.com>
Filling branch and commit independently let two checkouts share one provenance pair: an agent in another checkout that passed its branch but not its commit got the server's HEAD stored next to it, a pair no checkout ever had, in exactly the case explicit values exist for. Branch and commit are now resolved from git only when the caller gave neither (each empty or "unknown"). A caller that passes one passes both, or validation names the missing one, as it does for an omitted session_id. The schema descriptions and the MCP reference say so, and the provenance_required rows mention the "unknown" recorded when git cannot answer. The test helper also stops discarding its json.Marshal error. Spec: specs/fix-mcp-add-provenance.md Signed-off-by: Ersan Bilik <ersanbilik@gmail.com>
The ctx_add and ctx_watch_update rows called section "Target section in TASKS.md (tasks only)", but conventions take it too: it picks the ## section of CONVENTIONS.md the bullet goes under. Describe it as the schema does, required for tasks, without claiming it is tasks-only. Spec: specs/fix-mcp-add-provenance.md Signed-off-by: Ersan Bilik <ersanbilik@gmail.com>
bilersan
requested review from
CoderMungan,
hamzaerbay,
josealekhine and
parlakisik
as code owners
October 24, 2026 06:48
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
Over MCP,
ctx_addandctx_watch_updatecould not add a task, decision,or learning in a project without a relaxing
.ctxrc:entry.Validaterequires
session_id,branch, andcommit(andsectionfor tasks), butthe tool schemas never advertised them, so schema-driven clients never sent
them and every such call failed with
missing required fields: --session-id, --branch, --commit. This branchadvertises every field validation can require, resolves
branchandcommitfrom git on the server, keeps
session_idcaller-supplied and required, andflattens the single-line fields that end up inside
TASKS.mdlines andheadings. Decision and learning provenance is validated but never persisted;
that is raised on #190 and left out of this PR.
Fixes #190.
Changes
internal/mcp/server/def/tool):EntryAttrPropsdeclaressection,priority,session_id,branch, andcommit, so both entrytools take them from one definition;
ctx_watch_updategainssection/priority, which its handler already read. Servesspecs/fix-mcp-add-provenance.md.internal/mcp/server/route/tool): when the callergives neither
branchnorcommit(each empty or"unknown"),ctx_addandctx_watch_updateresolve both with the git calls the hookrelay makes in
provenance.Emitand its"unknown"fallback. Explicitvalues win, and the pair is resolved as a whole, so one checkout never
supplies the branch and another the commit.
session_idstays required:its description points at the relayed
Sessionvalue or an explicit"unknown", and the decision/learning prompt footers ask for it. Servesspecs/fix-mcp-add-provenance.md.internal/sanitize,internal/mcp/server/extract): thenew
sanitize.Linestrips every control character, including the tab, CR,and LF that
StripControlkeeps, and the Unicode line/paragraph separators,then truncates on a rune boundary.
SanitizedOptsapplies it topriority,section,branch, andcommitwithMaxOptsLineLen(256),the cap
specs/sanitize-hardening-followup.mddeferred for these fields.Serves
specs/fix-mcp-add-provenance.md.docs/cli/mcp.md,docs/home/configuration.md): the argumenttables of both tools list every advertised argument, with a provenance
note, and describe
sectionby what validation requires; theprovenance_requiredrows say how each key applies over MCP. Servesspecs/fix-mcp-add-provenance.md.Specs
specs/fix-mcp-add-provenance.md— how the MCP entry tools advertise,resolve, and sanitize the provenance fields entry validation requires
(committed on-branch)
Verification
internal/mcp/server/def/tool:TestDefsEntryToolsAdvertiseEntryFieldschecks that both entry tools advertise every field validation can require.
internal/mcp/server, end to end throughtools/call:TestToolEntryResolvesGitProvenance(both tools, in a temporary gitrepository, expected values read from git),
TestToolAddKeepsExplicitProvenance,TestToolAddBranchWithoutCommit(a branch without a commit fails, namingonly
--commit, instead of taking the server's HEAD),TestToolAddLearningUnknownSession(the ctx_add MCP tool requires provenance fields its own schema doesn't expose (task/decision/learning unusable over MCP) #190 probe with"session_id": "unknown"), andTestToolAddRequiresSessionID(omissionstill fails, naming only
--session-id).internal/sanitize:TestLine;internal/mcp/server/extract:TestSanitizedOptsFlattensLineFields.TestToolAddKeepsExplicitProvenance, which guards the explicit-value rule.