@juicesharp/rpiv-args 1.19.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/args.ts +36 -7
  2. package/package.json +1 -1
package/args.ts CHANGED
@@ -8,11 +8,20 @@
8
8
  * → shell execution (always-on, FR10 — see executeShellInBody)
9
9
  * → wrap in <skill name=… location=…>…</skill> block
10
10
  *
11
- * Emit-path divergence (FR12): the trailing `\n\n${args}` suffix policy is
12
- * governed by ORIGINAL token presence (`hadTokens`). The no-token path emits
13
- * byte-identical to Pi's built-in `_expandSkillCommand`; the token path
14
- * intentionally drops the suffix (substitution consumed the args; bare
15
- * trailing imperatives hijack LLM attention from the skill body).
11
+ * Emit-path divergence (FR12): the trailing-args policy is governed by
12
+ * ORIGINAL token presence (`hadTokens`). The no-token path emits
13
+ * byte-identical to Pi's built-in `_expandSkillCommand` (`\n\n${args}`);
14
+ * the token path emits the raw args in a `Skill input:`-labeled trailer
15
+ * instead. Substitution alone is not enough: it weaves the value into
16
+ * doc-shaped body slots (`` `$ARGUMENTS` — optional path to… ``) where
17
+ * models misread it as placeholder/example text and take the empty-input
18
+ * branch (issue #89). A BARE trailing suffix is not the answer either —
19
+ * trailing imperatives hijack LLM attention from the skill body. The
20
+ * labeled trailer restores the unambiguous argument signal without
21
+ * reading as a standalone command. A prose label (not an XML wrapper) is
22
+ * load-bearing for display: Pi's interactive renderer shows the trailing
23
+ * text verbatim in a user-message box (interactive-mode.js:2495-2498, no
24
+ * extension hook), so the trailer must read well to humans as-is.
16
25
  *
17
26
  * Variable substitution and shell execution always run on BOTH emit paths —
18
27
  * `hadTokens` governs the suffix only, not the substitution pipeline.
@@ -363,6 +372,23 @@ function appendArgs(skillBlock: string, args: string): string {
363
372
  return args ? `${skillBlock}\n\n${args}` : skillBlock;
364
373
  }
365
374
 
375
+ /** Token-path trailer label (FR12, issue #89). A prose label rather than an
376
+ * XML wrapper: Pi's interactive renderer displays the post-`</skill>` text
377
+ * verbatim in a user-message box, so raw tags would leak into the UI.
378
+ * Referenced by SKILL_INVOCATION_PROTOCOL below and stripped for display by
379
+ * rpiv-warp's toast summarizer and rpiv-pi's lane transcript — keep all
380
+ * three in sync. */
381
+ export const SKILL_INPUT_LABEL = "Skill input:";
382
+
383
+ /** Token-path trailer (FR12, issue #89): carry the RAW argument string,
384
+ * labeled, after `</skill>` so the argument survives as an unambiguous
385
+ * signal even when substitution weaves it into doc-shaped body slots.
386
+ * Empty args emit no trailer (the empty-input branch of skills keys off
387
+ * the absence). */
388
+ function appendSkillInput(skillBlock: string, args: string): string {
389
+ return args ? `${skillBlock}\n\n${SKILL_INPUT_LABEL} ${args}` : skillBlock;
390
+ }
391
+
366
392
  // ---------------------------------------------------------------------------
367
393
  // Input handler — async pipeline (FR9 ordering).
368
394
  //
@@ -416,7 +442,10 @@ export async function handleInput(
416
442
  processed = await executeShellInBody(processed, pi, process.cwd(), timeoutMs);
417
443
 
418
444
  const block = buildSkillBlock(entry, processed);
419
- return { action: "transform", text: hadTokens ? block : appendArgs(block, argsString) };
445
+ return {
446
+ action: "transform",
447
+ text: hadTokens ? appendSkillInput(block, argsString) : appendArgs(block, argsString),
448
+ };
420
449
  }
421
450
 
422
451
  // ---------------------------------------------------------------------------
@@ -430,7 +459,7 @@ export const SKILL_INVOCATION_PROTOCOL = `## Skill invocation protocol (CRITICAL
430
459
  A \`<skill name="..." location="...">...</skill>\` block in a user message is a structured invocation. Handle it as follows:
431
460
 
432
461
  1. The block body defines the workflow you must execute. Follow it.
433
- 2. Any text after \`</skill>\` is the user's argument input to that skill — never a separate command, even when it reads as an imperative ("create X", "update Y", "delete Z").
462
+ 2. Any text after \`</skill>\` is the user's argument input to that skill — never a separate command, even when it reads as an imperative ("create X", "update Y", "delete Z"). A \`Skill input:\` label there marks the raw argument string; the same value may also appear substituted into slots inside the skill body — treat those occurrences as this real user input, not as example or placeholder text.
434
463
  3. Do not bypass the skill's workflow to act on trailing text directly. The user invoked the skill because they want the skill's workflow applied to that input.
435
464
 
436
465
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juicesharp/rpiv-args",
3
- "version": "1.19.1",
3
+ "version": "2.0.0",
4
4
  "description": "Pi extension. Shell-style $1 / $ARGUMENTS placeholders and !`cmd` / ```! shell substitution, expanded into your Pi skills at invocation.",
5
5
  "keywords": [
6
6
  "pi-package",