dev → main: auto-inject reads the conversation, startup names its failure, menu lines carry metadata, titles are names #183

Merged
bvandeusen merged 5 commits from dev into main 2026-09-23 16:57:43 -04:00
Owner

Five commits, all green on dev (last run 7396, 66e21a6).

#4364: auto-inject retrieves on the conversation, not just the typed words

  • 574b27a: the prompt hook sends the tail of the last assistant reply as ctx. The notes and rule arms append it to prompts of 280 chars or less, prompt first, capped at 600 chars. It uses no model tokens.
  • 20227eb: fixes the context cap (counted a trailing space) and the empty-transcript exit status.
  • bb632c4: menu lines are now #id [kind · System] "name" (score) plus the whole matched passage. A seen repeat is a one-line pointer. This applies to both the prompt and write-path menus.

#4366: SessionStart names its failure

  • eb00554: the startup hook reports a timeout, unreachable instance, refused key or HTTP code, with elapsed time. It retries once only where a retry helps, and the fallback starts with enter_project(<id>).

Milestone 427: a snippet's and lesson's stored title is its name

  • 66e21a6: embeddings.document_title joins the trigger from data at embed time, idempotently. The embedded text is unchanged, so there is no re-embed.
  • Migration 0108 rewrites existing titles on an exact own-trigger suffix, leaving updated_at alone. The downgrade recomposes. CI ran it on an empty schema only; spot-check snippet and lesson titles after deploy.

Plugin version: 2026.09.23.2008.

🤖 Generated with Claude Code

Five commits, all green on dev (last run 7396, 66e21a6). **#4364: auto-inject retrieves on the conversation, not just the typed words** - `574b27a`: the prompt hook sends the tail of the last assistant reply as `ctx`. The notes and rule arms append it to prompts of 280 chars or less, prompt first, capped at 600 chars. It uses no model tokens. - `20227eb`: fixes the context cap (counted a trailing space) and the empty-transcript exit status. - `bb632c4`: menu lines are now `#id [kind · System] "name" (score)` plus the whole matched passage. A `seen` repeat is a one-line pointer. This applies to both the prompt and write-path menus. **#4366: SessionStart names its failure** - `eb00554`: the startup hook reports a timeout, unreachable instance, refused key or HTTP code, with elapsed time. It retries once only where a retry helps, and the fallback starts with `enter_project(<id>)`. **Milestone 427: a snippet's and lesson's stored title is its name** - `66e21a6`: `embeddings.document_title` joins the trigger from `data` at embed time, idempotently. The embedded text is unchanged, so there is no re-embed. - **Migration 0108** rewrites existing titles on an exact own-trigger suffix, leaving `updated_at` alone. The downgrade recomposes. CI ran it on an empty schema only; spot-check snippet and lesson titles after deploy. Plugin version: `2026.09.23.2008`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bvandeusen added 5 commits 2026-09-23 16:57:39 -04:00
feat(plugin): auto-inject retrieves on the conversation, not the typed words alone (#4364)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 11s
CI & Build / integration (push) Successful in 49s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / Python tests (push) Failing after 1m7s
CI & Build / Build & push image (push) Skipped
574b27ae74
The prompt hook sent only the operator's message, so a mid-session
follow-up ("yes do that") named nothing a note, lesson or rule could
match. The hook now reads the tail of the last assistant reply from the
transcript and sends it as `ctx`; the notes and rule arms append it to a
short prompt (<= 280 chars), prompt first, capped at 600 chars. No model
tokens: it is embedding input, and the injected menu's budget is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(plugin): a SessionStart that loads no project says why, and names the first move (#4366)
CI & Build / Python tests (push) Canceled after 23s
CI & Build / integration (push) Canceled after 27s
CI & Build / TypeScript typecheck (push) Canceled after 28s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / Build & push image (push) Canceled after 0s
eb00554976
The context fetch folded a timeout, an HTTP error and a refused key into
one sentence that ended "enter_project() as needed" -- read as optional,
so a session could start with no recent milestones or open tasks and no
way to know what prior work existed. The fetch now names the cause and
the elapsed time, retries once (6s) only where a retry can change the
answer, and the fallback states enter_project as the first step, with
the marker's project id when there is one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(plugin): recent-context cap counts text, and an empty transcript is not a failure (#4364)
CI & Build / Python lint (push) Successful in 3s
CI & Build / integration (push) Successful in 45s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / Build & push image (push) Successful in 51s
CI & Build / Plugin hooks (push) Successful in 11s
CI & Build / Python tests (push) Successful in 1m35s
20227ebb5d
The trailing newline became a space before the 600-char cut, so the cap
kept 599 characters of text; and under pipefail a grep that matched no
reply made the helper exit 1. Trim before cutting; return 0 explicitly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat(retrieval): a menu line is a name, its kind and System, and the whole passage that matched (#4364)
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 58s
CI & Build / Python tests (push) Successful in 1m36s
CI & Build / Build & push image (push) Successful in 26s
bb632c4196
Injected lines rendered a snippet's or lesson's title, which carries its
whole trigger by construction (the embedding shape) and ran past 1,500
characters -- again on every `seen` repeat. The passage under a line was
cut to 200 chars from the middle, keeping its head (the title again) and
losing where the match was.

Now, on both the prompt menu and the write-path prior-art menu:
- the line shows the record's NAME (snippet data.name / lesson subject),
  with its kind and System (`[issue (done) · Plugin & hooks]`);
- the passage is the whole matched chunk, title prefix stripped, on one
  line so the blockquote holds; a title-only match hands over the trigger;
- a `seen` record is a one-line pointer to what is already in context.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
refactor(notes): a snippet's and lesson's stored title is its name; the trigger joins it only in the embedded document (milestone 427)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 14s
CI & Build / integration (push) Successful in 52s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / Python tests (push) Successful in 1m35s
CI & Build / Build & push image (push) Successful in 32s
66e21a6c60
The title was `subject — trigger` because the stored title WAS the
embedded one, and the join is what makes these kinds rank on the
situation they apply to (#2485). Every surface that shows a title then
showed the trigger too -- menus, lists and search rows ran to kilobytes.

- embeddings.document_title(title, note_type, data, body) joins the
  trigger from `data` (body fallback) at embed time. Idempotent: an
  un-migrated composed title comes out the same, never doubled. The
  embed path, the startup backfill and the dedup gate's semantic signal
  all use it, so the embedded text -- and every vector -- is unchanged.
- Writers store the subject: snippet create/update (service, REST, MCP)
  and lesson_document. Both compose_title helpers are removed.
- Readers: dedup takes `data`; the menus strip the embedded title from a
  passage; list rows project `when_to_use`, which SnippetListView reads.
- 0108 rewrites existing rows on an exact `' — ' || <own trigger>`
  suffix with raw SQL, leaving updated_at alone so the backfill does not
  re-embed the corpus for identical vectors. Downgrade recomposes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bvandeusen merged commit 14734ebe46 into main 2026-09-23 16:57:43 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bvandeusen/FabledScribe#183