fix(prompting): allowed magic keyword punctuation
Magic keyword matching now treats sentence punctuation and quotes as prose boundaries while still rejecting casing changes, inflections, and path/file-extension occurrences. Added regression coverage for detection and highlighting across ultrathink, orchestrate, and workflowz. Fixes #4965
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
/** Characters that bind a magic keyword into an identifier or path segment. */
|
||||
const LEFT_BOUNDARY = String.raw`(?<![\p{L}\p{N}_./\\-])`;
|
||||
|
||||
/** Characters that cannot immediately follow a standalone magic keyword. */
|
||||
const RIGHT_BOUNDARY = String.raw`(?![\p{L}\p{N}_/\\-])(?!\.[\p{L}\p{N}_-])`;
|
||||
|
||||
/** Escape a literal string for safe insertion into a RegExp source. */
|
||||
function escapeRegExp(value: string): string {
|
||||
return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a case-sensitive magic-keyword matcher for prose punctuation boundaries.
|
||||
*
|
||||
* Sentence punctuation and quotes may touch the keyword, but letters, digits,
|
||||
* underscores, slashes, backslashes, hyphens, and file-extension dots keep the
|
||||
* occurrence embedded in another token or path.
|
||||
*/
|
||||
export function magicKeywordRegex(keyword: string, flags = ""): RegExp {
|
||||
const normalizedFlags = flags.includes("u") ? flags : `${flags}u`;
|
||||
return new RegExp(`${LEFT_BOUNDARY}${escapeRegExp(keyword)}${RIGHT_BOUNDARY}`, normalizedFlags);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import orchestrateNotice from "../prompts/system/orchestrate-notice.md" with { type: "text" };
|
||||
import { createGradientHighlighter, type KeywordHighlighter } from "./gradient-highlight";
|
||||
import { magicKeywordRegex } from "./magic-keyword-boundary";
|
||||
import { keywordInProse } from "./markdown-prose";
|
||||
|
||||
/**
|
||||
@@ -8,21 +9,21 @@ import { keywordInProse } from "./markdown-prose";
|
||||
* Typing the standalone word in the input editor paints it with a cool
|
||||
* teal→violet gradient ({@link highlightOrchestrate}); submitting a message that
|
||||
* mentions it appends a hidden {@link ORCHESTRATE_NOTICE} that switches the model
|
||||
* into multi-agent orchestration mode. Matching is whitespace-delimited and
|
||||
* into multi-agent orchestration mode. Matching is prose-delimited and
|
||||
* case-sensitive (lowercase only), so "orchestrated", "Orchestrate", or a path
|
||||
* like "orchestrate.ts" never trigger either behavior. Replaces the former
|
||||
* `/orchestrate` slash command.
|
||||
*/
|
||||
|
||||
// Detection: lowercase keyword flanked by whitespace or a string edge. Non-global so `.test` stays stateless.
|
||||
const ORCHESTRATE_WORD = /(?<!\S)orchestrate(?!\S)/;
|
||||
// Detection: lowercase keyword flanked by prose punctuation, whitespace, or a string edge.
|
||||
const ORCHESTRATE_WORD = magicKeywordRegex("orchestrate");
|
||||
|
||||
/** Hidden system notice appended after a user message that mentions "orchestrate". */
|
||||
export const ORCHESTRATE_NOTICE: string = orchestrateNotice.trim();
|
||||
|
||||
/**
|
||||
* Whether `text` contains the standalone keyword "orchestrate" (lowercase,
|
||||
* whitespace-delimited) in prose — never inside a code block, inline code span,
|
||||
* prose-delimited) in prose — never inside a code block, inline code span,
|
||||
* or XML/HTML section.
|
||||
*/
|
||||
export function containsOrchestrate(text: string): boolean {
|
||||
@@ -36,7 +37,7 @@ export function containsOrchestrate(text: string): boolean {
|
||||
*/
|
||||
export const highlightOrchestrate: KeywordHighlighter = createGradientHighlighter({
|
||||
probe: /orchestrate/,
|
||||
highlight: /(?<!\S)orchestrate(?!\S)/g,
|
||||
highlight: magicKeywordRegex("orchestrate", "g"),
|
||||
stops: 14,
|
||||
hue: t => 150 + t * 130,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ultrathinkNotice from "../prompts/system/ultrathink-notice.md" with { type: "text" };
|
||||
import { createGradientHighlighter, type KeywordHighlighter } from "./gradient-highlight";
|
||||
import { magicKeywordRegex } from "./magic-keyword-boundary";
|
||||
import { keywordInProse } from "./markdown-prose";
|
||||
|
||||
/**
|
||||
@@ -13,15 +14,15 @@ import { keywordInProse } from "./markdown-prose";
|
||||
* trigger either behavior.
|
||||
*/
|
||||
|
||||
// Detection: lowercase keyword flanked by whitespace or a string edge. Non-global so `.test` stays stateless.
|
||||
const ULTRATHINK_WORD = /(?<!\S)ultrathink(?!\S)/;
|
||||
// Detection: lowercase keyword flanked by prose punctuation, whitespace, or a string edge.
|
||||
const ULTRATHINK_WORD = magicKeywordRegex("ultrathink");
|
||||
|
||||
/** Hidden system notice appended after a user message that mentions "ultrathink". */
|
||||
export const ULTRATHINK_NOTICE: string = ultrathinkNotice.trim();
|
||||
|
||||
/**
|
||||
* Whether `text` contains the standalone keyword "ultrathink" (lowercase,
|
||||
* whitespace-delimited) in prose — never inside a code block, inline code span,
|
||||
* prose-delimited) in prose — never inside a code block, inline code span,
|
||||
* or XML/HTML section.
|
||||
*/
|
||||
export function containsUltrathink(text: string): boolean {
|
||||
@@ -35,7 +36,7 @@ export function containsUltrathink(text: string): boolean {
|
||||
*/
|
||||
export const highlightUltrathink: KeywordHighlighter = createGradientHighlighter({
|
||||
probe: /ultrathink/,
|
||||
highlight: /(?<!\S)ultrathink(?!\S)/g,
|
||||
highlight: magicKeywordRegex("ultrathink", "g"),
|
||||
stops: 14,
|
||||
hue: t => t * 330,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { prompt } from "@oh-my-pi/pi-utils";
|
||||
import workflowNoticeTemplate from "../prompts/system/workflow-notice.md" with { type: "text" };
|
||||
import { createGradientHighlighter, type KeywordHighlighter } from "./gradient-highlight";
|
||||
import { magicKeywordRegex } from "./magic-keyword-boundary";
|
||||
import { keywordInProse } from "./markdown-prose";
|
||||
|
||||
/**
|
||||
@@ -10,13 +11,13 @@ import { keywordInProse } from "./markdown-prose";
|
||||
* amber→green gradient ({@link highlightWorkflow}); submitting a message that
|
||||
* mentions it appends a hidden workflow notice that steers the model to author
|
||||
* a deterministic multi-subagent workflow through the active task schema.
|
||||
* Matching is whitespace-delimited and case-sensitive (lowercase only) —
|
||||
* Matching is prose-delimited and case-sensitive (lowercase only) —
|
||||
* "workflowz" triggers, but "workflowzed", "Workflowz", and "workflowz.ts"
|
||||
* never do.
|
||||
*/
|
||||
|
||||
// Detection: lowercase keyword flanked by whitespace or a string edge. Non-global so `.test` stays stateless.
|
||||
const WORKFLOW_WORD = /(?<!\S)workflowz(?!\S)/;
|
||||
// Detection: lowercase keyword flanked by prose punctuation, whitespace, or a string edge.
|
||||
const WORKFLOW_WORD = magicKeywordRegex("workflowz");
|
||||
|
||||
/** WORKFLOW_NOTICE is the default hidden notice for sessions with batched task calls enabled. */
|
||||
export const WORKFLOW_NOTICE: string = renderWorkflowNotice({ taskBatch: true });
|
||||
@@ -28,7 +29,7 @@ export function renderWorkflowNotice({ taskBatch }: { taskBatch: boolean }): str
|
||||
|
||||
/**
|
||||
* Whether `text` contains the standalone keyword "workflowz"
|
||||
* (lowercase, whitespace-delimited) in prose — never inside a code block, inline
|
||||
* (lowercase, prose-delimited) in prose — never inside a code block, inline
|
||||
* code span, or XML/HTML section.
|
||||
*/
|
||||
export function containsWorkflow(text: string): boolean {
|
||||
@@ -42,7 +43,7 @@ export function containsWorkflow(text: string): boolean {
|
||||
*/
|
||||
export const highlightWorkflow: KeywordHighlighter = createGradientHighlighter({
|
||||
probe: /workflowz/,
|
||||
highlight: /(?<!\S)workflowz(?!\S)/g,
|
||||
highlight: magicKeywordRegex("workflowz", "g"),
|
||||
stops: 14,
|
||||
hue: t => 30 + t * 120,
|
||||
});
|
||||
|
||||
@@ -51,20 +51,20 @@ Decompose first, then {{#if taskBatch}}batch the independent leaves{{else}}issue
|
||||
|
||||
{{#if taskBatch}}
|
||||
task(
|
||||
context: "# Goal\nReview the auth diff...\n# Constraints\nRead-only...\n# Contract\nReturn findings as severity/file/line/fix...",
|
||||
context: "# Goal\nReview the auth diff…\n# Constraints\nRead-only…\n# Contract\nReturn findings as severity/file/line/fix…",
|
||||
tasks: [
|
||||
{ id: "AuthOwner", role: "Auth Storage Reviewer", assignment: "# Target\npackages/ai/src/auth-storage.ts\n# Change\nTrace credential selection...\n# Acceptance\nReturn confirmed findings only..." },
|
||||
{ id: "PromptOwner", role: "Prompt Contract Reviewer", assignment: "# Target\npackages/coding-agent/src/prompts/**\n# Change\nCheck active-tool guidance...\n# Acceptance\nReturn mismatches and exact prompt lines..." },
|
||||
{ id: "AuthOwner", role: "Auth Storage Reviewer", assignment: "# Target\npackages/ai/src/auth-storage.ts\n# Change\nTrace credential selection…\n# Acceptance\nReturn confirmed findings only…" },
|
||||
{ id: "PromptOwner", role: "Prompt Contract Reviewer", assignment: "# Target\npackages/coding-agent/src/prompts/**\n# Change\nCheck active-tool guidance…\n# Acceptance\nReturn mismatches and exact prompt lines…" },
|
||||
]
|
||||
)
|
||||
{{else}}
|
||||
task(
|
||||
role: "Auth Storage Reviewer",
|
||||
assignment: "# Target\npackages/ai/src/auth-storage.ts\n# Change\nReview the auth diff. Shared contract: read-only; return findings as severity/file/line/fix.\n# Acceptance\nReturn confirmed findings only..."
|
||||
assignment: "# Target\npackages/ai/src/auth-storage.ts\n# Change\nReview the auth diff. Shared contract: read-only; return findings as severity/file/line/fix.\n# Acceptance\nReturn confirmed findings only…"
|
||||
)
|
||||
task(
|
||||
role: "Prompt Contract Reviewer",
|
||||
assignment: "# Target\npackages/coding-agent/src/prompts/**\n# Change\nCheck active-tool guidance. Shared contract: read-only; return mismatches and exact prompt lines.\n# Acceptance\nReturn confirmed findings only..."
|
||||
assignment: "# Target\npackages/coding-agent/src/prompts/**\n# Change\nCheck active-tool guidance. Shared contract: read-only; return mismatches and exact prompt lines.\n# Acceptance\nReturn confirmed findings only…"
|
||||
)
|
||||
{{/if}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user