fix(plugin): the session-start Goal line cuts at a word and says where the rest is (#4036)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 58s
CI & Build / Python tests (push) Successful in 1m27s
CI & Build / Build & push image (push) Successful in 26s

A raw 200-char slice ended mid-word with nothing marking the cut, so a
reader took half a sentence for the whole goal. _goal_line flattens the
goal to one line, trims at a word break with an ellipsis, and points at
enter_project(id) when it cut.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-14 15:34:36 -04:00
co-authored by Claude Opus 5
parent c440c49f5b
commit 21343dc3aa
2 changed files with 49 additions and 1 deletions
+23 -1
View File
@@ -16,6 +16,7 @@ from __future__ import annotations
import logging
import re
import textwrap
import time
@@ -41,6 +42,10 @@ _MAX_CHARS = 9000
# Max chars of a Process body to fold into the auto-surface description.
_PROC_PREVIEW_CHARS = 200
# Max chars of the project goal on the session-start Goal line. The full goal is
# one enter_project away; a cut says so rather than ending mid-word (#4036).
_GOAL_CHARS = 200
# --- Knowledge auto-inject (Path A: per-turn awareness push) -----------------
# Per-user settings (keys live in the generic settings table). The threshold is
# deliberately STRICTER than the pull-search default (embeddings
@@ -2140,6 +2145,23 @@ def _stamp_line(path: str, stamped: list[dict]) -> str:
def _goal_line(goal: str, project_id: int) -> str:
"""The Goal line, trimmed at a word break with a visible cut.
A raw slice ended mid-word with nothing to say more existed, so a reader
took half a sentence for the whole goal (#4036).
"""
if not goal:
return ""
flat = " ".join(goal.split())
if len(flat) <= _GOAL_CHARS:
return f"Goal: {flat}"
short = textwrap.shorten(flat, width=_GOAL_CHARS, placeholder="")
if short == "": # one unbroken word longer than the cap
short = flat[: _GOAL_CHARS - 1] + ""
return f"Goal: {short} (full goal: `enter_project({project_id})`)"
async def build_session_context(
user_id: int, project_id: int = 0, unbound_repo: str = ""
) -> dict:
@@ -2185,7 +2207,7 @@ async def build_session_context(
lines += [
"",
f"## Active project: {project.title} (id {project.id})",
f"Goal: {goal[:200]}" if goal else "",
_goal_line(goal, project.id),
f"Open todo tasks: {open_count}",
]