Repository navigation
harvest: user messages wrapped in <pasted_content …> are treated as meta, so pasted briefs never become tasks #318
Description
Version examined
microsoft/SkillOptmain@343db229dbd5ddaf9df6b1d5540d8bcdb2604d5c(2026-10-06), packageskillopt_sleep.- Claude Code plugin
skillopt-sleep0.1.0 from the same commit. - Windows 11 Pro (build 26300), Python 3.12.13, plugin runner started from Git Bash 5.3.
- Transcripts written by the Claude Code desktop app (Code tab), version 2.1.271.
Observed behavior
_is_meta_prompt() (skillopt_sleep/harvest.py, lines 137-155) treats any text that starts with < and ends with > as system noise (line 142).
The desktop app stores pasted text in the user message wrapped in a tag pair carrying the same id: <pasted_content id="…"> … </pasted_content id="…">. We verified this on our own transcripts by checking only the opening and closing tag, without exporting their content. A pasted brief is therefore dropped, and it is often the main request of the session.
Three consequences, all reproduced below with synthetic data:
- Wrong intent. If the user then writes a short follow-up such as "Yes, go ahead with option A.", that follow-up becomes the mined task intent, because
heuristic_mine()takes the first surviving prompt (skillopt_sleep/mine.py, line 175). - Session silently lost. If the pasted brief is the only user message,
n_user_turnsis 0._is_headless_replay()(harvest.py, lines 217-218) then classifies the session as one of the engine's own replays, and the whole session is dropped, although it contains real assistant work. - Related. A user message that starts with a host-injected
<system-reminder>…</system-reminder>block and then contains the real request does not end with>, so it is kept, but the reminder block is copied verbatim into the task intent.
In a real run, 2 of 5 hand-picked sessions were mined from the wrong message for reason 1.
Expected behavior
- Treat
<pasted_content …>blocks as user content: strip the wrapper tags and keep the inner text as the user's intent. - Limit the "meta" heuristic to known host and system tags (for example
<command-message>,<command-name>,<local-command-stdout>,<system-reminder>) instead of any text wrapped in angle brackets. - Strip host-injected
<system-reminder>blocks from intents. - Do not classify a session that has real assistant turns as a headless replay only because all its user turns were filtered out.
Minimal synthetic reproduction
No model calls and no network. Run from the repository root, or set SKILLOPT_REPO to it.
"""Synthetic repro: pasted briefs are dropped by the harvest meta filter (no model calls, no network)."""
import json
import os
import sys
import tempfile
sys.path.insert(0, os.environ.get("SKILLOPT_REPO", "."))
from skillopt_sleep.harvest import _is_meta_prompt, harvest # noqa: E402
from skillopt_sleep.mine import heuristic_mine # noqa: E402
ROOT = tempfile.mkdtemp(prefix="skillopt-d19-")
PROJECT = os.path.join(ROOT, "proj")
TRANSCRIPTS = os.path.join(ROOT, "projects")
os.makedirs(PROJECT)
BRIEF = ('<pasted_content id="a1b2">\nInstall tool X into a dedicated folder, pin the version, '
'back up the configs first and write a short report.\n</pasted_content id="a1b2">')
REMINDER = ('<system-reminder>\nStatus note injected by the host app.\n</system-reminder>\n\n'
'Yes: run the third review on range r2..abc1234 and update the report.')
def session(sid, turns):
folder = os.path.join(TRANSCRIPTS, "proj")
os.makedirs(folder, exist_ok=True)
with open(os.path.join(folder, sid + ".jsonl"), "w", encoding="utf-8") as f:
for i, (role, text) in enumerate(turns):
f.write(json.dumps({"type": role, "cwd": PROJECT, "sessionId": sid,
"timestamp": f"2026-01-01T10:{i:02d}:00Z",
"message": {"role": role, "content": text}}) + "\n")
session("s1-pasted-then-followup", [("user", BRIEF), ("assistant", "Plan: ..."),
("user", "Yes, go ahead with option A."), ("assistant", "Done.")])
session("s2-pasted-only", [("user", BRIEF), ("assistant", "Plan: ..."), ("assistant", "Done.")])
session("s3-reminder-prefix", [("user", REMINDER), ("assistant", "Running the review.")])
print("_is_meta_prompt(BRIEF) =", _is_meta_prompt(BRIEF))
digests = harvest(TRANSCRIPTS, scope="invoked", invoked_project=PROJECT)
print("harvested sessions:", sorted(d.session_id for d in digests))
for t in heuristic_mine(digests):
print(f"task from {t.source_sessions[0]}: intent = {t.intent!r}")Output at the commit above:
_is_meta_prompt(BRIEF) = True
harvested sessions: ['s1-pasted-then-followup', 's3-reminder-prefix']
task from s3-reminder-prefix: intent = '<system-reminder>\nStatus note injected by the host app.\n</system-reminder>\n\nYes: run the third review on range r2..abc1234 and update the report.'
task from s1-pasted-then-followup: intent = 'Yes, go ahead with option A.'
s2-pasted-only is missing from the harvested sessions: the pasted brief was its only user message.
Related
- fix(harvest): exclude sub-agent transcripts and agent-generated sessions from task mining #99 extended
_is_meta_prompt()to skip expanded slash-command bodies (<command-message>,<command-name>,# /…). - fix(sleep): skip Claude Code isMeta records when harvesting user prompts #295 skips records marked
isMeta: trueand leaves the text heuristics of_is_meta_prompt()unchanged. - Neither covers
<pasted_content>: a pasted brief is typed by the user and is not markedisMeta. We found no open or closed issue or PR about it.
Not verified
- Whether the Claude Code terminal CLI, or other clients, use the same
<pasted_content>wrapper. We observed it only in the desktop app. - Whether other host tags that wrap a whole user message exist and are dropped the same way.
Activity
Yif-Yang commentedon Oct 18, 2026
#321 fixes the original pasted-brief loss, including pasted-only sessions and follow-up requests. The new review also finds two regressions: literal user examples containing a system-reminder tag lose their content, and a known host-only record can consume the session cap ahead of a real request. Both have current-main controls and independent verification. The issue stays open while the author retains the useful unwrap behavior and corrects those content/cap boundaries.
Yif-Yang commentedon Oct 23, 2026
The updated #321 fixes leading-reminder contamination, the host-only session-cap regression and genuine pasted-brief recovery. It still globally strips
<pasted_content>tags from user-authored inline and fenced parser examples, changing the digest and mined intent; those examples survive on current main. The requested follow-up is to distinguish host wrappers from literal user text while preserving the passing reminder, pasted-brief and Copilot privacy controls. This issue remains open and the current PR should not merge with that regression.