Skip to content

feat(prompts): stable bare-name invocation identity and a manage_prompt use verb#1019

Merged
cjimti merged 2 commits into
mainfrom
feat/1008-prompt-stable-identity
Jul 22, 2026
Merged

feat(prompts): stable bare-name invocation identity and a manage_prompt use verb#1019
cjimti merged 2 commits into
mainfrom
feat/1008-prompt-stable-identity

Conversation

@cjimti

@cjimti cjimti commented Jul 22, 2026

Copy link
Copy Markdown
Member

Closes #1008

Summary

A prompt now has one canonical name for its entire life. Database prompts are served on the native MCP prompts surface under their bare stored names, promotion never renames a prompt, every prompt descriptor carries a human-readable title, and a new manage_prompt use command lets an agent resolve and run a prompt from any handle a user might say out loud. The platform steers agents to resolve named procedures against the prompt library instead of enumerating it.

Bare names with per-viewer precedence

Previously each database prompt was presented under a per-viewer scope-prefixed name (global-<name>, <persona>-<name>, personal-<name>, shared-<name>), so promoting a personal prompt to a shared scope silently renamed it at exactly the moment it became a team SOP. Now prompts/list and prompts/get serve every visible prompt under its bare stored name, resolved per viewer with deterministic precedence: personal > shared-with-me > persona > global.

Shadowing is visible, never silent: when several visible prompts share a name, the winner keeps the bare name and each shadowed prompt is still listed under its legacy scope-qualified fallback name with an annotated description, and prompts/get resolves those qualified forms. A qualified fallback that would collide with a stored bare name (or another qualified entry) is resolved deterministically so the list and prompts/get always agree; collisions between qualified entries keep the one the legacy prefix resolution serves.

Static registry prompts (the auto-generated overview, operator config, workflow, and toolkit prompts) keep bare-name authority: the handle snapshots their names at registration and the serving callbacks decline them, so a database prompt can never shadow a built-in. Persona prompts now appear once per prompt instead of once per matching persona.

Compatibility

Clients or saved workflows that learned the old prefixed names keep working: prompts/get still resolves personal-, global-, shared-, and <persona>- prefixed forms through a deprecation window, falling through to persona resolution for personas literally named after reserved tokens, exactly as before.

Titles everywhere

promptDescriptor, operator, and workflow prompt registration now set the MCP Title field from display_name, falling back to the machine name. server.prompts[].display_name is a new config field, registry.PromptInfo carries display_name, the four built-in workflow prompts gained human titles, and ingested system rows inherit the display name.

manage_prompt use: resolve and run

use accepts any handle in name and returns the prompt ready to run:

  • an exact bare name (daily-sales-report), resolved with the same precedence as the native surface and including system rows, so built-ins resolve too
  • a display name, case-insensitively ("Daily Sales Report"), with scope precedence applied to collisions and a candidate list on ties
  • an mcp:prompt:<id> reference (the same reference search results carry), with visibility enforced per caller and share access matched by prompt ID
  • free text, ranked by the hybrid searcher within the caller's visibility; a single result or a top score clearing a confidence margin resolves, anything else returns ranked candidates; stores without ranking degrade to a substring match with space-to-hyphen normalization

A resolved response carries the rendered content (values passed in args are substituted), the argument specs, any required arguments still missing, and provenance (scope, lifecycle status, approver, owner, reference) so the agent can confirm what it is about to run. An ambiguous handle returns status: "ambiguous" with up to five candidates, never an error and never a silent first match.

Agent steering

The platform_info instruction baseline gains a bullet, gated on manage_prompt being reachable, telling agents that named procedures are prompts and to resolve them with use rather than enumerate. The tool description carries the same guidance.

Testing

  • Assembled-system integration tests: a real mcp.Server with the real prompt-visibility middleware and an in-memory client session prove that a personal prompt shadowing a same-named global serves the personal bare, lists the global qualified and annotated, agrees between prompts/list and prompts/get on every listed name, carries titles through the protocol, and leaves an unshadowed viewer untouched.
  • Unit tests cover bare precedence, static-name authority, qualified-name collision handling, legacy prefix compatibility, anonymous fail-closed behavior, and every use resolution path including ID-scoped share visibility, argument substitution, missing-argument reporting, ranked confidence and ambiguity, and provenance fields.
  • Coverage: promptlayer at 94.5%, every new or changed function at or above 80%. make verify green.

Docs

Configuration reference (naming and resolution semantics, display_name field), tools reference (manage_prompt section and summary row), portal user guide (naming section rewritten), and both llms files updated.

cjimti added 2 commits July 21, 2026 22:21
…pt use verb (#1008)

Database prompts are served over MCP under their bare stored names with
deterministic per-viewer precedence (personal > shared-with-me > persona >
global), so promoting a prompt never changes the name anyone invokes. A
shadowed prompt stays listed under its legacy scope-qualified name with an
annotated description, legacy prefixed names keep resolving on prompts/get,
and static registry prompts retain bare-name authority so a database prompt
cannot shadow a built-in. Every prompt descriptor now carries an MCP title
from display_name (new server.prompts[].display_name config field; workflow
prompts gained human titles).

manage_prompt gains a use command that resolves any handle - bare name,
display name (case-insensitive), mcp:prompt:<id> reference, or free text via
ranked search with a confidence margin - and returns the rendered content,
argument specs, missing required arguments, and provenance, or ranked
candidates when ambiguous. Share access on reference lookups is matched by
prompt ID. The platform_info instruction baseline and the tool description
steer agents to resolve named procedures with use instead of enumerating.

Includes an assembled-system integration test (real mcp.Server + prompt
visibility middleware + in-memory client) covering a personal prompt
shadowing a same-named global, plus docs updates (configuration, tools,
portal user guide, llms files).
…ve-first steering

Restores the scope-prefixed presentation names for database prompts: the
prefix scheme keeps the native MCP prompts surface collision-free by
construction, and a personal prompt has an audience of one before promotion,
so renaming at promotion carries no cost worth trading that invariant for.
ListVisible, GetByName, the visibility middleware, and their tests are back
to their previous semantics.

What remains from the original change: the manage_prompt use command
(resolve any handle - stored name, display name, mcp:prompt:<id>, or free
text - to rendered content with argument specs and provenance, ranked
candidates when ambiguous, share access matched by prompt ID), MCP titles
from display_name on database, operator, and workflow prompt descriptors
(new server.prompts[].display_name config field, human titles on the four
workflow prompts), and the platform_info steering that tells agents to
resolve named procedures with use instead of enumerating. Users never see
presented names: use insulates them entirely.

Integration tests prove the prefix contract and title propagation through a
real mcp.Server with the real prompt-visibility middleware; docs re-pointed
accordingly.
@cjimti
cjimti merged commit 09edf9d into main Jul 22, 2026
8 checks passed
@cjimti
cjimti deleted the feat/1008-prompt-stable-identity branch July 22, 2026 06:21
@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.06349% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.29%. Comparing base (7d800f8) to head (9ba5cf9).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
internal/platform/promptlayer/use.go 94.94% 6 Missing and 4 partials ⚠️
internal/platform/promptlayer/tool.go 60.86% 9 Missing ⚠️
internal/platform/promptlayer/register.go 95.23% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1019      +/-   ##
==========================================
+ Coverage   89.25%   89.29%   +0.04%     
==========================================
  Files         457      458       +1     
  Lines       50487    50726     +239     
==========================================
+ Hits        45063    45297     +234     
- Misses       3611     3616       +5     
  Partials     1813     1813              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

prompts: stable invocation identity and a resolve-and-run verb

1 participant