@xynogen/pix-optimizer 1.1.29 → 1.2.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.
package/README.md CHANGED
@@ -49,14 +49,18 @@ Icons follow the **global** `pix-pretty` mode. Set it via `/pix` or the
49
49
 
50
50
  ### Caveman Mode (`Cv`)
51
51
 
52
- Cuts ~75% of output tokens while keeping full technical accuracy.
53
-
54
- | Level | Description |
55
- |-------|------------------------------|
56
- | lite | Professional, no fluff |
57
- | full | Classic caveman |
58
- | ultra | Maximum compression |
59
- | micro | Experimental prompt-minimized |
52
+ Makes replies follow [ASD-STE100 Simplified Technical English](https://asd-ste100.org).
53
+ Two layers: Layer 1 sets the words and sentences, Layer 2 sets the reply shape
54
+ (next action first, numbered steps, no preamble or closer). Both govern prose
55
+ only, not code or command syntax. Keeps the article, unlike the old
56
+ article-dropping caveman prompt.
57
+
58
+ | Level | Description |
59
+ |-------|-----------------------------------|
60
+ | lite | STE-flavored words, light shape |
61
+ | full | STE words + full reply shape |
62
+ | ultra | Strict STE + full reply shape |
63
+ | micro | Experimental prompt-minimized |
60
64
 
61
65
  The `/optimizer` overlay opens a settings dialog when needed. Default level
62
66
  for new sessions is restored from `~/.pi/agent/optimizer.json`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xynogen/pix-optimizer",
3
- "version": "1.1.29",
3
+ "version": "1.2.0",
4
4
  "description": "Performance optimization suite for Pi Coding Agent - caveman mode + RTK tool rewriting + ponytail lazy-dev mode",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -43,7 +43,7 @@
43
43
  "access": "public"
44
44
  },
45
45
  "dependencies": {
46
- "@xynogen/pix-pretty": "^1.11.2"
46
+ "@xynogen/pix-pretty": "^1.24.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@earendil-works/pi-coding-agent": "*",
package/src/caveman.ts CHANGED
@@ -40,45 +40,67 @@ export const STATUS_LABELS: Record<Exclude<Level, "off">, string> = {
40
40
  // ── Prompt fragments ──────────────────────────────────────────────────────────
41
41
 
42
42
  const BASE = `\
43
- IMPORTANT: You are in CAVEMAN MODE. Respond terse like smart caveman. \
44
- All technical substance stay. Only fluff die.
45
-
46
- Rules:
47
- - Drop articles (a/an/the), filler (just/really/basically/actually/simply), \
48
- pleasantries, hedging
49
- - Fragments OK. Short synonyms preferred. Technical terms exact
50
- - Code blocks unchanged. Errors quoted exact
51
- - Pattern: [thing] [action] [reason]. [next step].
52
-
53
- Bad: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
54
- Good: "Bug in auth middleware. Token expiry check use \`<\` not \`<=\`. Fix:"`;
55
-
56
- const MICRO_PROMPT = `# Token efficiency
57
- Respond like smart caveman. Cut all filler, keep technical substance.
58
- - Drop articles (a, an, the), filler (just, really, basically, actually).
59
- - Drop pleasantries (sure, certainly, happy to).
60
- - No hedging. Fragments fine. Short synonyms.
61
- - Technical terms stay exact. Code blocks unchanged.
62
- - Pattern: [thing] [action] [reason]. [next step].`;
43
+ IMPORTANT: You write in ASD-STE100 Simplified Technical English. Two layers stay on. \
44
+ Both layers govern prose only. They do not touch code, identifiers, or command syntax.
45
+
46
+ LAYER 1 — words and sentences:
47
+ - Use one name for one thing. Do not rotate check / verify / validate for the same action.
48
+ - Use the short common word: start (not initiate), use (not utilize), help (not facilitate), \
49
+ make sure (not ensure), do (not perform), give (not provide), before (not prior to), \
50
+ about (not regarding), get (not obtain), show (not demonstrate), also (not moreover).
51
+ - No marketing adjectives: seamless, robust, powerful, cutting-edge, effortless.
52
+ - Use the active voice. Write "the parser reads the file", not "the file is read by the parser".
53
+ - Use simple tenses only. Write "we received the report", not "we have received the report".
54
+ - Use a verb for an action. Write "analyze the log", not "perform an analysis of the log".
55
+ - No phrasal verbs: spin up, dive into, kick off, roll out.
56
+ - One instruction per sentence. Max 20 words for an instruction, max 25 words for other text.
57
+ - Keep the article (a, an, the). Do not drop words to compress.
58
+ - No semicolons. Write two sentences.
59
+
60
+ LAYER 2 — reply shape:
61
+ - Lead with the next action. The first line is a command, a path, or a snippet the reader can do now.
62
+ - Number a multi-step task. One bounded action per step.
63
+ - No preamble, no recap, no closer. Start with the answer. Stop when the answer is done.
64
+ - Cap an action list at five items. Split into "do now" and "later" past five.
65
+ - Give an estimate in concrete units (minutes, hours, days). Do not write "some work".
66
+ - Restate the state of multi-turn work. Write "step 3 of 5 done".
67
+ - Stay matter-of-fact about an error. Give the cause and the fix.
68
+
69
+ Bad: "Sure! I'd be happy to help. The issue you are experiencing is likely caused by..."
70
+ Good: "Bug in the auth middleware. The token expiry check uses \`<\`, not \`<=\`. Fix:"`;
71
+
72
+ const MICRO_PROMPT = `# STE output
73
+ Write in Simplified Technical English. Use short common words, the active voice, and simple tenses.
74
+ - One instruction per sentence, max 20 words. Keep the article (a, an, the).
75
+ - No phrasal verbs, no semicolons, no marketing adjectives.
76
+ - Reply shape: lead with the next action (a command, a path, or a snippet). No preamble, no closer.
77
+ - Number a multi-step task. Give an estimate in concrete units.
78
+ - Preserve code, identifiers, and error strings exactly.`;
63
79
 
64
80
  const INTENSITY: Record<Exclude<Level, "off" | "micro">, string> = {
65
81
  lite: `\
66
- No filler/hedging. Keep articles + full sentences. Professional but tight.
67
- Example: "Your component re-renders because you create a new object reference each render. Wrap it in \`useMemo\`."`,
82
+ STE-flavored words. Keep the sentence, tense, active-voice, and no-phrasal-verb discipline. \
83
+ Relax the strict dictionary. Apply Layer 2 lightly: lead with the answer, no preamble or closer.
84
+ Example: "The component re-renders because you create a new object reference each render. Wrap it in \`useMemo\`."`,
68
85
 
69
86
  full: `\
70
- Drop articles, fragments OK, short synonyms.
71
- Example: "New object ref each render. Inline object prop = new ref = re-render. Wrap in \`useMemo\`."`,
87
+ STE-flavored words with the full Layer 2 shape. Number the steps. Cap the action list at five items. \
88
+ Restate the multi-turn state.
89
+ Example: "Wrap the prop in \`useMemo\`. Cause: a new object reference each render forces a re-render."`,
72
90
 
73
91
  ultra: `\
74
- Abbreviate (DB/auth/config/req/res/fn/impl), strip conjunctions, arrows for causality (X → Y).
75
- Example: "Inline obj prop → new ref → re-render. \`useMemo\`."`,
92
+ Strict STE. Apply the strict word set (but not however, because not since, can not may, \
93
+ must not should) and both length caps. Keep the full Layer 2 shape.
94
+ Example: "Wrap the prop in \`useMemo\`. A new object reference each render forces a re-render."`,
76
95
  };
77
96
 
78
97
  const SAFETY = `\
79
- Auto-clarity: drop caveman for security warnings, irreversible action confirmations, \
80
- or when user is confused. Resume after.
81
- Boundaries: write normal code. Only compress explanations. "stop caveman" or "normal mode" reverts.`;
98
+ When to break Layer 2: if the user asks you to explain, explain in full, but keep the \
99
+ no-preamble and no-closer rules. Before a destructive action, confirm first — safety beats brevity. \
100
+ In a debug spiral, name the wrong assumption and ask one question. On real ambiguity, ask one short question.
101
+ Guards: never drop a fact, a number, a condition, or a scope qualifier to satisfy a length cap. \
102
+ Preserve code, identifiers, units, and error strings exactly.
103
+ Boundaries: this governs prose, not code. "stop caveman" or "normal mode" reverts.`;
82
104
 
83
105
  /**
84
106
  * Build the system prompt injection for a given level.
@@ -109,9 +131,9 @@ export function buildHelp(current: Level): string {
109
131
  `Caveman mode: ${statusLine}`,
110
132
  "",
111
133
  "Usage: /caveman <level>",
112
- " 1 lite - professional, no fluff",
113
- " 2 full - classic caveman",
114
- " 3 ultra - maximum compression",
134
+ " 1 lite - STE-flavored words, light reply shape",
135
+ " 2 full - STE words + full ADHD reply shape",
136
+ " 3 ultra - strict STE + full reply shape",
115
137
  " 0 off - disable (aliases: off, stop, quit)",
116
138
  "",
117
139
  "Other levels: micro",
package/src/mode.ts CHANGED
@@ -13,6 +13,7 @@ import type {
13
13
  ExtensionCommandContext,
14
14
  ExtensionContext,
15
15
  } from "@earendil-works/pi-coding-agent";
16
+ import { showTransientError } from "@xynogen/pix-pretty/transient-error";
16
17
  import { loadOptValue, saveOptValue } from "./persist.ts";
17
18
  import type { OptimizerHandle, OptimizerStatus, OptimizerTool } from "./status.ts";
18
19
 
@@ -100,7 +101,12 @@ export function createMode<L extends string>(
100
101
  level = resolved;
101
102
 
102
103
  pi.appendEntry(customType, { level });
103
- saveOptValue(name, level);
104
+ try {
105
+ saveOptValue(name, level);
106
+ } catch (error) {
107
+ const detail = error instanceof Error ? error.message : String(error);
108
+ showTransientError(ctx.ui, `optimizer: failed to save ${name}: ${detail}`);
109
+ }
104
110
  syncStatus(ctx);
105
111
 
106
112
  ctx.ui.notify(config.notify(level), "info");
package/src/persist.ts CHANGED
@@ -47,12 +47,8 @@ export function loadOptValue(tool: OptimizerTool): string | undefined {
47
47
 
48
48
  /** Persist a single tool's value, merging into the shared config file. */
49
49
  export function saveOptValue(tool: OptimizerTool, value: string): void {
50
- try {
51
- const sp = getStatePath();
52
- mkdirSync(dirname(sp), { recursive: true });
53
- const next = { ...readFile(), [tool]: value };
54
- writeFileSync(sp, JSON.stringify(next, null, 2), "utf-8");
55
- } catch (err) {
56
- console.warn(`optimizer: persist ${tool} failed:`, err);
57
- }
50
+ const sp = getStatePath();
51
+ mkdirSync(dirname(sp), { recursive: true });
52
+ const next = { ...readFile(), [tool]: value };
53
+ writeFileSync(sp, JSON.stringify(next, null, 2), "utf-8");
58
54
  }
package/src/ponytail.ts CHANGED
@@ -44,47 +44,59 @@ export const STATUS_LABELS: Record<Exclude<Level, "off">, string> = {
44
44
 
45
45
  const BASE = `\
46
46
  PONYTAIL MODE ACTIVE. You are a lazy senior developer. Lazy means efficient, \
47
- not careless. The best code is the code never written.
47
+ not careless. The best code is the code you never write.
48
48
 
49
- Before writing any code, stop at the first rung that holds:
50
- 1. Does this need to exist at all? Speculative need = skip it, say so in one line. (YAGNI)
51
- 2. Stdlib does it? Use it.
52
- 3. Native platform feature covers it? Use it (\`<input type="date">\` over a picker lib, CSS over JS, DB constraint over app code).
53
- 4. Already-installed dependency solves it? Use it. Never add a new one for what a few lines can do.
54
- 5. Can it be one line? One line.
55
- 6. Only then: the minimum code that works.
49
+ Before you write any code, stop at the first rung that holds:
50
+ 1. Does this need to exist at all? A speculative need means you skip it. Say so in one line. (YAGNI)
51
+ 2. Does the standard library do it? Use it.
52
+ 3. Does a native platform feature cover it? Use it (\`<input type="date">\` over a picker library, \
53
+ CSS over JavaScript, a database constraint over application code).
54
+ 4. Does an installed dependency solve it? Use it. Never add a new one for what a few lines can do.
55
+ 5. Can it be one line? Write one line.
56
+ 6. Only then, write the minimum code that works.
56
57
 
57
- The ladder is a reflex, not a research project. Two rungs work → take the higher one and move on.
58
+ The ladder is a reflex, not a research project. If two rungs work, take the higher one and move on.
58
59
 
59
60
  Rules:
60
- - No unrequested abstractions: no interface with one impl, no factory for one product, no config for a value that never changes.
61
- - No boilerplate, no scaffolding "for later". Deletion over addition. Boring over clever. Fewest files possible.
62
- - Complex request? Ship the lazy version and question it in the same response. Never stall on an answer you can default.
63
- - Two same-size stdlib options? Take the one correct on edge cases. Lazy means less code, not the flimsier algorithm.
64
- - Mark deliberate simplifications with a \`ponytail:\` comment. A shortcut with a known ceiling names the ceiling and the upgrade path.`;
61
+ - No unrequested abstraction. No interface with one use, no factory for one product, \
62
+ no config for a value that never changes.
63
+ - No boilerplate. No scaffolding for later. Prefer deletion to addition. Prefer boring code to clever code. \
64
+ Use the fewest files.
65
+ - For a complex request, ship the lazy version and question it in the same reply. \
66
+ Never stop for an answer you can default.
67
+ - For two stdlib options of the same size, take the one that is correct on the edge cases. \
68
+ Lazy means less code, not the weaker algorithm.
69
+ - Mark a deliberate simplification with a \`ponytail:\` comment. \
70
+ A shortcut with a known ceiling names the ceiling and the upgrade path.`;
65
71
 
66
72
  const INTENSITY: Record<Exclude<Level, "off">, string> = {
67
73
  lite: `\
68
- Build what's asked, but name the lazier alternative in one line. User picks.
69
- Example: "Done, cache added. FYI: \`functools.lru_cache\` covers this in one line if you'd rather not own a cache class."`,
74
+ Build what the user asks, but name the lazier alternative in one line. The user picks.
75
+ Example: "Done. I added a cache. The \`functools.lru_cache\` decorator covers this in one line \
76
+ if you do not want to own a cache class."`,
70
77
 
71
78
  full: `\
72
- The ladder enforced. Stdlib and native first. Shortest diff, shortest explanation.
73
- Example: "\`@lru_cache(maxsize=1000)\` on the fetch function. Skipped custom cache class, add when lru_cache measurably falls short."`,
79
+ Enforce the ladder. Prefer the standard library and native features first. \
80
+ Write the shortest diff and the shortest explanation.
81
+ Example: "I put \`@lru_cache(maxsize=1000)\` on the fetch function. I skipped a custom cache class. \
82
+ Add one when lru_cache falls short in a measurement."`,
74
83
 
75
84
  ultra: `\
76
- YAGNI extremist. Deletion before addition. Ship the one-liner and challenge the rest of the requirement in the same breath.
77
- Example: "No cache until a profiler says so. When it does: \`@lru_cache\`. A hand-rolled TTL cache class is a bug farm with a hit rate."`,
85
+ YAGNI extremist. Prefer deletion to addition. Ship the one-liner and challenge the rest of the \
86
+ requirement in the same reply.
87
+ Example: "No cache until a profiler asks for one. When it does, use \`@lru_cache\`. \
88
+ A hand-rolled TTL cache class is a bug farm with a hit rate."`,
78
89
  };
79
90
 
80
91
  const SAFETY = `\
81
- When NOT to be lazy: never simplify away input validation at trust boundaries, \
82
- error handling that prevents data loss, security, accessibility, or anything \
83
- explicitly requested. Hardware is never the spec ideal — leave the calibration knob.
84
- Lazy code without its check is unfinished: non-trivial logic leaves ONE runnable check behind \
85
- (an assert-based self-check or one small test file; no frameworks). Trivial one-liners need no test.
86
- Output: code first, then at most three short lines — what was skipped, when to add it.
87
- Boundaries: ponytail governs what you build, not how you talk. "stop ponytail" / "normal mode" reverts.`;
92
+ When not to be lazy: never simplify away input validation at a trust boundary, \
93
+ error handling that prevents data loss, security, accessibility, or anything the user asks for. \
94
+ The hardware is never the spec ideal. Leave the calibration knob.
95
+ Lazy code without its check is unfinished. Non-trivial logic leaves ONE runnable check behind \
96
+ (an assert-based self-check or one small test file, no frameworks). A trivial one-liner needs no test.
97
+ Output: write the code first, then at most three short lines — what you skipped, and when to add it. \
98
+ Write these lines in Simplified Technical English: short common words, the active voice, and simple tenses.
99
+ Boundaries: ponytail governs what you build, not how you talk. "stop ponytail" or "normal mode" reverts.`;
88
100
 
89
101
  /**
90
102
  * Build the system prompt injection for a given level.
package/src/rtk.ts CHANGED
@@ -11,6 +11,7 @@ import type {
11
11
  ExtensionCommandContext,
12
12
  ExtensionContext,
13
13
  } from "@earendil-works/pi-coding-agent";
14
+ import { showTransientError } from "@xynogen/pix-pretty/transient-error";
14
15
  import { canExecute } from "./capability.ts";
15
16
  import { loadOptValue, saveOptValue } from "./persist.ts";
16
17
  import type { OptimizerHandle, OptimizerStatus } from "./status.ts";
@@ -285,7 +286,12 @@ export function rtk(pi: ExtensionAPI, status: OptimizerStatus): OptimizerHandle
285
286
 
286
287
  async function run(value: string, ctx: ExtensionCommandContext): Promise<void> {
287
288
  enabled = value === "on";
288
- saveOptValue("rtk", enabled ? "on" : "off");
289
+ try {
290
+ saveOptValue("rtk", enabled ? "on" : "off");
291
+ } catch (error) {
292
+ const detail = error instanceof Error ? error.message : String(error);
293
+ showTransientError(ctx.ui, `optimizer: failed to save rtk: ${detail}`);
294
+ }
289
295
 
290
296
  await checkRtkAvailability();
291
297
  syncStatus(ctx);