dsh-persona-forge 0.3.1 → 0.8.3
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/CHANGELOG.md +671 -1
- package/README.en.md +260 -108
- package/README.md +157 -50
- package/assets/menu.png +0 -0
- package/assets/review-panel.png +0 -0
- package/assets/settings.png +0 -0
- package/cards/muscle-crew.yml +140 -100
- package/cards/omnissiah.yml +152 -98
- package/lib/client.js +589 -320
- package/lib/index.js +0 -16
- package/lib/preserve.js +11 -16
- package/lib/prompts.js +183 -110
- package/lib/rewrite.js +97 -58
- package/lib/routes.js +80 -51
- package/lib/store.js +19 -3
- package/package.json +2 -1
package/README.en.md
CHANGED
|
@@ -9,7 +9,7 @@ character's voice by the harness LLM before it is sent — following the model
|
|
|
9
9
|
the session is already using. Choose whether the rewrite goes straight out or
|
|
10
10
|
lands back in the composer for review.
|
|
11
11
|
|
|
12
|
-
> **Status:** early (`0.
|
|
12
|
+
> **Status:** early (`0.8.x`). The card format and the HTTP contract are stable
|
|
13
13
|
> enough to build on; expect additive changes and read the changelog before
|
|
14
14
|
> upgrading.
|
|
15
15
|
|
|
@@ -30,12 +30,36 @@ an explicit action.
|
|
|
30
30
|
|
|
31
31
|
### A word on what personas actually do
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
raise the model's capability ceiling: there is no dormant potential that
|
|
36
|
-
naming an identity unlocks.
|
|
33
|
+
First, a fact: a persona does **not** unlock hidden capability. There is no
|
|
34
|
+
dormant potential that naming an identity wakes up — the ceiling is the ceiling.
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
But the other half is true too: **a persona really does change how the model
|
|
37
|
+
thinks.** It changes style, register, length and **compliance** — how readily
|
|
38
|
+
the model agrees, how willing it is to push back, and how seriously it will
|
|
39
|
+
commit to an absurd metaphor.
|
|
40
|
+
|
|
41
|
+
This project was born in that second, slightly unreasonable place. The
|
|
42
|
+
inspiration is a 30-second video on Bilibili:
|
|
43
|
+
|
|
44
|
+
> [**“ds:好的,我现在是万机之神了(”**](https://www.bilibili.com/video/BV1Ata26pE92) — by 身居幻想乡の长乐安生
|
|
45
|
+
|
|
46
|
+
The comments put it better than any spec sheet:
|
|
47
|
+
|
|
48
|
+
> Another AI is you pretending to be Guan Yu — however well you act, you are not
|
|
49
|
+
> Guan Yu. But when **Big Fat Fish** pretends to be Guan Yu, she genuinely
|
|
50
|
+
> believes she is Guan Yu, and really does ride out and cut down Hua Xiong.
|
|
51
|
+
|
|
52
|
+
"Okay, I am the Machine God now" — the model is not *humouring* the bit. It has
|
|
53
|
+
**accepted the identity**. What this plugin does is make that moment reusable:
|
|
54
|
+
put a character card in front of your draft, and let DeepSeek speak as that
|
|
55
|
+
character.
|
|
56
|
+
|
|
57
|
+
**It is tuned for DeepSeek Flash.** Flash is fast, cheap and plentiful — the
|
|
58
|
+
tier you actually use all day — and letting it answer you once in the voice of
|
|
59
|
+
the Machine God is the entire point. It runs on other models too, but that
|
|
60
|
+
"one line and it is in character" feel was tuned against Flash.
|
|
61
|
+
|
|
62
|
+
**So do not treat it as a performance switch.** Two things worth knowing:
|
|
39
63
|
|
|
40
64
|
1. A persona that frames you as a supplicant and the model as an authority
|
|
41
65
|
makes the model **less likely to question your plan**. For coding work that
|
|
@@ -43,8 +67,12 @@ Two consequences worth knowing before you use this:
|
|
|
43
67
|
deference.
|
|
44
68
|
2. "Longer and more ornate" is easy to mistake for "better". It usually is not.
|
|
45
69
|
|
|
46
|
-
|
|
47
|
-
|
|
70
|
+
Use it for tone and framing, keep **review mode** on, and judge the output by
|
|
71
|
+
whether your requirements survived — not by how impressive it sounds.
|
|
72
|
+
|
|
73
|
+
> The two bundled cards are the two tempers of that video: **万机之神 · 欧姆弥赛亚**
|
|
74
|
+
> is the solemn Mechanicum litany, and **肌肉集团 · 硬邦邦** is its antidote — a
|
|
75
|
+
> machine-gun-tempo crude client who says it all in fewer words than the litany.
|
|
48
76
|
|
|
49
77
|
---
|
|
50
78
|
|
|
@@ -128,33 +156,71 @@ you want them gone.
|
|
|
128
156
|
|
|
129
157
|
1. Click 🎭 in the composer tool row and pick a character. **No persona**, at the
|
|
130
158
|
end of the same list, turns rewriting off — that is the state the control
|
|
131
|
-
starts in
|
|
132
|
-
2.
|
|
159
|
+
starts in. **Which character you are using is remembered per session.**
|
|
160
|
+
2. The selected character grows its own **"Settings for <name>"** row right
|
|
161
|
+
under it. Open it for **intensity**, **send mode**, **rewrite mode** and
|
|
162
|
+
**fidelity**:
|
|
133
163
|
- Intensity is a four-rung ladder: **Light · Medium · Strong · Zealot**
|
|
134
164
|
(轻 · 中 · 重 · 狂热). Light adds a touch of flavour; Medium is clear but not
|
|
135
165
|
dominant; Strong gives the voice real weight while keeping the request the
|
|
136
166
|
first thing the reader sees; Zealot is ritual throughout. A card carries
|
|
137
|
-
its own default, and this choice overrides it
|
|
167
|
+
its own default, and this choice overrides it.
|
|
138
168
|
- **Review first** — the rewrite appears in the comparison panel below the
|
|
139
169
|
composer; you read it and then press Send there. Your draft is untouched
|
|
140
170
|
until you confirm.
|
|
141
|
-
- **Send directly** — the rewrite is sent as your message immediately, and
|
|
142
|
-
|
|
143
|
-
|
|
171
|
+
- **Send directly** — the rewrite is sent as your message immediately, and the
|
|
172
|
+
panel then **closes itself**. There is nothing left to confirm, and a panel
|
|
173
|
+
left up would block the next message.
|
|
144
174
|
3. With a character selected, the composer's normal **Send** button — or
|
|
145
175
|
**Enter** — *is* the rewrite trigger.
|
|
146
176
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
177
|
+
<img src="assets/menu.png" alt="The character menu: three cards, No persona, and the selected character's expanded settings (intensity, send mode, rewrite mode, fidelity)" width="400">
|
|
178
|
+
|
|
179
|
+
**Everything that configures a character lives in its own "Settings for <name>"
|
|
180
|
+
fold, and follows the CHARACTER rather than the session.** "硬邦邦 always goes out
|
|
181
|
+
Zealot, un-reviewed" is a fact about that character rather than a temporary
|
|
182
|
+
choice in one conversation — so configure it once and picking it in another
|
|
183
|
+
session gives you the same settings. Switching character **re-reads that
|
|
184
|
+
character's own settings** rather than carrying the previous one's intensity
|
|
185
|
+
across.
|
|
186
|
+
|
|
187
|
+
That fold holds four things:
|
|
188
|
+
|
|
189
|
+
| | |
|
|
190
|
+
|---|---|
|
|
191
|
+
| **Intensity** | Light · Medium · Strong · Zealot |
|
|
192
|
+
| **Send mode** | Review first / Send directly |
|
|
193
|
+
| **Rewrite mode** | Card default / Model rewrite / Template |
|
|
194
|
+
| **Fidelity** | Card default / Voice only / Constraints too |
|
|
195
|
+
|
|
196
|
+
Every row explains itself on **hover** rather than in permanent prose. The folded
|
|
197
|
+
row itself **summarises the current settings**, so you can see what a character is
|
|
198
|
+
set to without opening it.
|
|
199
|
+
|
|
200
|
+
**All four follow the character card** — pick it in another session and you get
|
|
201
|
+
the same set.
|
|
202
|
+
|
|
203
|
+
**The card directory has exactly one entry point: the settings page.** It is not
|
|
204
|
+
in the rewrite menu — it is occasional housekeeping, and it should not sit in the
|
|
205
|
+
path of choosing a character.
|
|
206
|
+
|
|
207
|
+
**The rewrite column is editable.** What the model wrote is a starting point,
|
|
208
|
+
not a verdict: fixing a dropped identifier or a tone that is slightly off by hand
|
|
209
|
+
is faster than another round trip. Once you edit it the panel says so, and
|
|
210
|
+
**Send** and **Fill** both carry *your* text.
|
|
211
|
+
|
|
212
|
+
<img src="assets/review-panel.png" alt="The review panel: the original draft on the left, the editable rewrite on the right, and beneath them the local check verdict, model and elapsed time, plus Send / Restore original / Rewrite" width="820">
|
|
213
|
+
|
|
214
|
+
**While the panel is open, the composer's send arrow is deliberately inert.** The
|
|
215
|
+
panel is the decision point; pressing send now would either push the un-reviewed
|
|
216
|
+
draft out or start a second rewrite of the same draft. Pick an action in the
|
|
217
|
+
panel, or close it, and the composer comes back.
|
|
152
218
|
|
|
153
219
|
The rewrite runs **once per draft**: after a rewrite lands, sending goes through
|
|
154
220
|
as-is instead of rewriting the output again. Editing the draft re-arms it.
|
|
155
221
|
|
|
156
|
-
Your draft is preserved: *Restore original* puts it back, and
|
|
157
|
-
|
|
222
|
+
Your draft is preserved: *Restore original* puts it back, and also rewinds the
|
|
223
|
+
"already rewritten" memory, so a rewrite you cancelled can be run again.
|
|
158
224
|
|
|
159
225
|
### How send interception works, and its one risk
|
|
160
226
|
|
|
@@ -186,40 +252,28 @@ message.
|
|
|
186
252
|
|
|
187
253
|
### The preservation check
|
|
188
254
|
|
|
189
|
-
After each rewrite, a second call on the same model compares the rewrite
|
|
190
|
-
against your original and reports whether technical content survived:
|
|
191
|
-
|
|
192
255
|
The biggest risk is not a voice that sounds wrong — it is a rewrite that
|
|
193
|
-
**quietly loses your request**.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
tokens** of the draft against the rewrite, in this process: identifiers, file
|
|
198
|
-
paths, versions, numbers, `--flag`s, acronyms like `API`. Anything lost is
|
|
199
|
-
**named** ("Lost: a.js"). It calls no model, so it costs no tokens and adds no
|
|
200
|
-
latency — and it cannot be turned off.
|
|
256
|
+
**quietly loses your request**. The plugin compares the **technical tokens** of
|
|
257
|
+
the draft against the rewrite, in this process: identifiers, file paths,
|
|
258
|
+
versions, numbers, `--flag`s, acronyms like `API`. Anything lost is **named**
|
|
259
|
+
("Lost: a.js").
|
|
201
260
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
at all:
|
|
261
|
+
It calls **no model**, so it costs no tokens and adds no latency — and it cannot
|
|
262
|
+
be turned off. It always runs.
|
|
205
263
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
264
|
+
**What it cannot see** (and the panel says so, so you do not assume more): a
|
|
265
|
+
requirement reworded into something **weaker** while every word survives, a
|
|
266
|
+
constraint **added in prose**, a quantity written in Chinese words (「两次」), or
|
|
267
|
+
a bare lowercase English word that is not a path, flag or identifier.
|
|
209
268
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
269
|
+
> A second layer once existed: one **extra model call** per rewrite aimed
|
|
270
|
+
> exactly at those cases. It has been **removed** — it doubled the latency and
|
|
271
|
+
> the token cost of every send, and the most common and most damaging failure (a
|
|
272
|
+
> dropped filename, number or version) was already proven for free. For the
|
|
273
|
+
> residue, **the rewrite column is editable**, which is more direct than another
|
|
274
|
+
> round trip.
|
|
215
275
|
|
|
216
|
-
The
|
|
217
|
-
global preference: it answers "do I want to pay for the second call", which is
|
|
218
|
-
decided once rather than re-asked on the way to every send. With it off the panel
|
|
219
|
-
states plainly that the local check ran and spent no tokens, and says what that
|
|
220
|
-
check does **not** cover — a narrow verdict has to declare its own limits.
|
|
221
|
-
|
|
222
|
-
Both layers are **advisory** and never block a rewrite: they annotate, not stop.
|
|
276
|
+
The check is **advisory** and never blocks a rewrite: it annotates, it does not stop.
|
|
223
277
|
|
|
224
278
|
---
|
|
225
279
|
|
|
@@ -232,9 +286,9 @@ in makes the character appear without a restart**.
|
|
|
232
286
|
~/.dsh/persona-cards/<id>.yml
|
|
233
287
|
```
|
|
234
288
|
|
|
235
|
-
Use
|
|
236
|
-
You can also create and edit cards entirely in
|
|
237
|
-
writes the same files.
|
|
289
|
+
Use *Open directory* in **Settings → Persona** to get there (the rewrite menu no
|
|
290
|
+
longer carries an entry). You can also create and edit cards entirely in
|
|
291
|
+
**Settings → Persona**; that writes the same files.
|
|
238
292
|
|
|
239
293
|
On first run the bundled cards are **copied into your card directory** so the
|
|
240
294
|
folder is a usable starting point. A copy shadows the bundled card of the same
|
|
@@ -267,25 +321,66 @@ draft box sits at the **top of the form that opens**, not as a second competing
|
|
|
267
321
|
entry on the page. A hint line on the settings page tells you it exists, so you
|
|
268
322
|
do not have to press a button to discover it.
|
|
269
323
|
|
|
270
|
-
|
|
324
|
+
<img src="assets/settings.png" alt="The 角色扮演 settings page: New character card and the expanded AI draft's Generate draft are boxed, and the footer names the harness default model this run will use" width="420">
|
|
325
|
+
|
|
326
|
+
**You** write one sentence: **who the AI plays, who you are, and how they talk.**
|
|
271
327
|
|
|
272
|
-
> a grumpy but utterly reliable old lighthouse keeper
|
|
273
|
-
> sentences and nautical metaphors
|
|
328
|
+
> the AI plays a grumpy but utterly reliable old lighthouse keeper, and I am his
|
|
329
|
+
> apprentice; he speaks in short sentences and nautical metaphors
|
|
274
330
|
|
|
275
|
-
The
|
|
276
|
-
description, and the **conversion examples for all four
|
|
331
|
+
**The AI** then fills the form by the character-card fields: a name, an icon, a
|
|
332
|
+
description, the style text, and the **conversion examples for all four
|
|
333
|
+
intensity levels**.
|
|
334
|
+
|
|
335
|
+
> **The rewrite is always YOUR message, never the character's line.** If you say
|
|
336
|
+
> "the AI is my mother", the example must be **the child speaking to her mother**
|
|
337
|
+
> (`妈,帮我把标题改成首页好不好?`), **not** the mother speaking
|
|
338
|
+
> (~~`乖,妈帮你把标题改成首页`~~). Get this backwards and the card is useless —
|
|
339
|
+
> the rewrite comes out as the character answering for you.
|
|
340
|
+
|
|
341
|
+
The result **only fills the form — it is never saved automatically**. Two things
|
|
342
|
+
are deliberately fixed: **fidelity** is always voice-only, and **rewrite mode**
|
|
343
|
+
is always model rewrite. A generated card should not quietly acquire the power to
|
|
344
|
+
add constraints to your request; raise it by hand if you want it.
|
|
345
|
+
|
|
346
|
+
> **All four intensity sets must come back, or the generation counts as failed.**
|
|
347
|
+
> The examples are the longest part of a card, and a model occasionally runs out
|
|
348
|
+
> of output budget part-way through them. That used to be accepted as-is, which
|
|
349
|
+
> left the missing levels with **nothing to demonstrate** — it looked fine and was
|
|
350
|
+
> quietly worse. It now reports an error; retrying once is usually enough.
|
|
277
351
|
|
|
278
352
|
**Which model it uses has to be stated precisely:**
|
|
279
353
|
|
|
280
354
|
| Case | Which model |
|
|
281
355
|
|---|---|
|
|
282
|
-
| The **rewrite** from the 🎭 menu | **Follows the current session** (the provider/model of
|
|
356
|
+
| The **rewrite** from the 🎭 menu | **Follows the model the current session is using** — preferring the one you have just **picked in the model dropdown** (even before you send with it), then the provider/model of the session's last request |
|
|
283
357
|
| **AI draft** in the settings page | The **harness default model** — because `settings.section` receives only `{ close }` from the shell and therefore **has no session id to follow** |
|
|
284
358
|
|
|
285
359
|
These are usually the same model (the default is usually what the session is
|
|
286
360
|
using), but **not guaranteed**: if you switch models inside a session, the
|
|
287
361
|
settings page's draft still uses the default.
|
|
288
362
|
|
|
363
|
+
> The rewrite reads the host's own precedence: **pending pick → last request
|
|
364
|
+
> header → harness default**. So changing the model in the dropdown takes effect
|
|
365
|
+
> immediately, with no message to send first. Reading the request header alone
|
|
366
|
+
> sent a rewrite to the **previous** model whenever you had switched and not yet
|
|
367
|
+
> spoken — that was a bug, and it is fixed.
|
|
368
|
+
|
|
369
|
+
> What is followed is the **provider / model**; the **reasoning depth is never
|
|
370
|
+
> specified explicitly**. The rewrite sends no `reasoningEffort` field and lets
|
|
371
|
+
> the harness decide per route.
|
|
372
|
+
>
|
|
373
|
+
> That is not laziness, it is the only portable spelling. The harness validates
|
|
374
|
+
> the field *before* handing the request to any provider: when a route's model
|
|
375
|
+
> declares **no** reasoning metadata, **any present value throws** — including
|
|
376
|
+
> the empty string (the host's own "Provider default" sentinel) and including
|
|
377
|
+
> `off`. `hy4-preview` on `workbuddy-xdpool` is exactly such a route, and
|
|
378
|
+
> pinning `low` there broke every rewrite outright.
|
|
379
|
+
>
|
|
380
|
+
> The cost: on a reasoning model the rewrite may still spend thinking time
|
|
381
|
+
> before emitting text. The panel's elapsed seconds and the 120s deadline are
|
|
382
|
+
> the current answer to that.
|
|
383
|
+
|
|
289
384
|
So you do not have to guess, the settings page **shows the model it will use**
|
|
290
385
|
(`provider / model`) and says that it is the harness default; after generating it
|
|
291
386
|
shows the model it **actually** used. If neither can be resolved (no message sent
|
|
@@ -319,6 +414,14 @@ mode: llm # llm = model rewrite (recommended) | template
|
|
|
319
414
|
fidelity: style # style = voice only | strategy = may add constraints
|
|
320
415
|
intensity: medium # light | medium | strong | zealot (the card's default)
|
|
321
416
|
|
|
417
|
+
# The fixed wrapper for template mode: no model call, {{input}} is replaced
|
|
418
|
+
# verbatim with what you typed. Every card should carry one, or "Template" is a
|
|
419
|
+
# switch that does nothing.
|
|
420
|
+
template: |
|
|
421
|
+
万机之座在上,吾等是您卑微的信徒,谨向欧姆弥赛亚祷告:
|
|
422
|
+
{{input}}
|
|
423
|
+
恳请您垂听吾等的祈求。愿机魂安宁,愿数据各安其位。
|
|
424
|
+
|
|
322
425
|
# What the character IS. This is an instruction to the rewriting model, not
|
|
323
426
|
# finished copy: the output is written fresh for each of your messages.
|
|
324
427
|
style: |
|
|
@@ -326,32 +429,63 @@ style: |
|
|
|
326
429
|
【发言者方向】用「信徒」的口吻说话,向万机之神恳求……
|
|
327
430
|
语气:庄严、古奥、仪式化。
|
|
328
431
|
|
|
329
|
-
# Conversion demonstrations: input draft → persona voice.
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
# Optional: different demonstrations per intensity. If omitted for a level,
|
|
337
|
-
# the flat `examples` list is used instead.
|
|
432
|
+
# Conversion demonstrations: input draft → persona voice, one set per level.
|
|
433
|
+
#
|
|
434
|
+
# Four sets is all you need. An earlier version also had a flat `examples:` list,
|
|
435
|
+
# but it was only the fallback for a level with no set of its own — on a card
|
|
436
|
+
# with all four populated it was never reached, yet still had to be maintained.
|
|
437
|
+
# Write only this now. (A flat `examples:` in an older file is still READ and
|
|
438
|
+
# still falls back; it is just no longer something you need to write.)
|
|
338
439
|
examplesByIntensity:
|
|
339
440
|
light:
|
|
340
441
|
- from: 帮我写个快速排序
|
|
341
442
|
to: 万机之座在上,恳请您为我们编写一个快速排序算法。
|
|
443
|
+
medium:
|
|
444
|
+
- from: 帮我写个快速排序
|
|
445
|
+
to: >
|
|
446
|
+
万机之座在上,吾等恳请您赐予枢机之序的奥义:
|
|
447
|
+
请为我们编写一个快速排序算法,使重复之数各归其位。
|
|
448
|
+
strong:
|
|
449
|
+
- from: 帮我写个快速排序
|
|
450
|
+
to: 伟大而不朽的万机之神,恳请您赐予枢机之序的奥义……
|
|
342
451
|
zealot:
|
|
343
452
|
- from: 帮我写个快速排序
|
|
344
453
|
to: 伟大而不朽的万机之神……
|
|
454
|
+
|
|
455
|
+
# The SECOND set, shown when fidelity is `strategy`. All four levels again.
|
|
456
|
+
#
|
|
457
|
+
# It demonstrates "voice + behavioural framing" — framing being an instruction
|
|
458
|
+
# about HOW to do the work (do not over-plan, do not stop at the first plausible
|
|
459
|
+
# cause), never a restatement of the request. Without this set a user who raises
|
|
460
|
+
# fidelity gives the model nothing to imitate, and it pads instead.
|
|
461
|
+
examplesByIntensityStrategy:
|
|
462
|
+
light:
|
|
463
|
+
- from: 帮我写个快速排序
|
|
464
|
+
to: 万机之座在上,请为我们编写一个快速排序算法,径直给出可用之器。
|
|
465
|
+
medium:
|
|
466
|
+
- from: 帮我写个快速排序
|
|
467
|
+
to: >
|
|
468
|
+
万机之座在上,恳请您赐予枢机之序的奥义,使重复之数各归其位。
|
|
469
|
+
另有一请:请直取可行之解,不必先为吾等铺设长篇筹谋。
|
|
470
|
+
strong:
|
|
471
|
+
- from: 帮我写个快速排序
|
|
472
|
+
to: 伟大而不朽的万机之神,恳请您赐予枢机之序的奥义……勿止步于初见可行之解。
|
|
473
|
+
zealot:
|
|
474
|
+
- from: 帮我写个快速排序
|
|
475
|
+
to: 伟大而不朽的万机之神……其一,勿以理论充作交付;其二,勿满足于最初可行之解。
|
|
345
476
|
```
|
|
346
477
|
|
|
347
478
|
### The two rules that make a card work
|
|
348
479
|
|
|
349
|
-
**1. State the speaker direction.** The
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
that
|
|
354
|
-
model
|
|
480
|
+
**1. State the speaker direction.** The text being rewritten is always *yours*,
|
|
481
|
+
but **which side the character is on is your decision**: the AI can play the
|
|
482
|
+
character (and you address it as a petitioner, a client or a subordinate), or
|
|
483
|
+
**you can be** the character (speaking in its voice to the AI). Both are valid.
|
|
484
|
+
The only thing that goes wrong is **leaving it unsaid** — an implicit direction
|
|
485
|
+
leaves the model guessing, and guessing wrong inverts the whole relationship (a
|
|
486
|
+
petitioner's prayer comes out as the god issuing orders). Write it out
|
|
487
|
+
explicitly. The two bundled cards take one side each: 欧姆弥赛亚 is "the user is
|
|
488
|
+
a believer, the AI is the Machine God"; 硬邦邦 is "**the user is** the client".
|
|
355
489
|
|
|
356
490
|
**2. Make your examples preserve technical facts.** Examples are the strongest
|
|
357
491
|
style anchor, and the model imitates them — including their mistakes. If an
|
|
@@ -367,29 +501,50 @@ substance. Run it after editing a card.
|
|
|
367
501
|
|
|
368
502
|
| Value | Meaning | Use when |
|
|
369
503
|
|---|---|---|
|
|
370
|
-
| `style` | Voice only.
|
|
371
|
-
| `strategy` | The rewrite may **add behavioural
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
504
|
+
| `style` | Voice only. | Default. Almost always this. |
|
|
505
|
+
| `strategy` | The rewrite may **add behavioural framing**. | Deliberate cases — e.g. the bundled *肌肉集团* card, which adds "don't over-plan, don't search, don't ship beginner-tier solutions". |
|
|
506
|
+
|
|
507
|
+
**"Constraint" means two different things in this document — do not conflate
|
|
508
|
+
them:**
|
|
509
|
+
|
|
510
|
+
| | What it is | May it change? |
|
|
511
|
+
|---|---|---|
|
|
512
|
+
| **Technical content** | What you are asking for, which file, which number, which limit | **Never, under any setting** |
|
|
513
|
+
| **Behavioural framing** | How the assistant should approach the work — how direct, whether to plan first, what counts as good enough | `strategy` may add it |
|
|
514
|
+
|
|
515
|
+
What `strategy` adds is the **second** kind, and it **genuinely changes the
|
|
516
|
+
request you send** — it puts something in your message that you did not type. So
|
|
517
|
+
keep **Review first** on for those cards.
|
|
518
|
+
|
|
519
|
+
> The prompt used to conflate the two: the hard rules said "never add, remove,
|
|
520
|
+
> widen or reinterpret a requirement" while declaring themselves an override of
|
|
521
|
+
> everything *including the character description*, and the `strategy` permission
|
|
522
|
+
> was written before them. The model obeyed the absolute prohibition, so
|
|
523
|
+
> `strategy` was a **no-op** — flipping "Constraints too" in the UI changed
|
|
524
|
+
> nothing about the output. The hard rules now cover technical content only, and
|
|
525
|
+
> say explicitly that they do not forbid behavioural framing.
|
|
526
|
+
|
|
527
|
+
**Fidelity is a property of the card, but you can override it per character, in
|
|
528
|
+
both directions:**
|
|
529
|
+
|
|
530
|
+
| Option | Meaning |
|
|
531
|
+
|---|---|
|
|
532
|
+
| **Card default** | Use whatever the card declares on the settings page |
|
|
533
|
+
| **Voice only** | Wording changes; your request does not |
|
|
534
|
+
| **Constraints too** | The rewrite may also add the character's working style (e.g. "no long planning") |
|
|
535
|
+
|
|
536
|
+
**"Constraints too" genuinely changes your request**, rather than only rewording
|
|
537
|
+
it — it adds things you never typed. So pair it with **Review first**.
|
|
538
|
+
|
|
539
|
+
> This rule used to be one-way: a `strategy` card could be narrowed to `style`,
|
|
540
|
+
> but a `style` card could never be widened. The reasoning was that a click on
|
|
541
|
+
> the way to Send should not grant the power to add constraints to your request.
|
|
542
|
+
>
|
|
543
|
+
> That reasoning does not hold up: **the card is your own file**, and the
|
|
544
|
+
> settings page has always let you set `fidelity:` directly. Refusing in the menu
|
|
545
|
+
> did not remove the capability — it only made the choice **disappear from the
|
|
546
|
+
> place where you actually work**. All three options are now available on every
|
|
547
|
+
> card.
|
|
393
548
|
|
|
394
549
|
### `mode: template`
|
|
395
550
|
|
|
@@ -409,16 +564,12 @@ Set in the plugin's loader row config:
|
|
|
409
564
|
name: dsh-persona-forge
|
|
410
565
|
config:
|
|
411
566
|
sendMode: review # review | direct — the initial composer default
|
|
412
|
-
factCheck: false # default for the MODEL check (off by default; see
|
|
413
|
-
# "The preservation check"). The local token check does
|
|
414
|
-
# not depend on this: it always runs and is free.
|
|
415
567
|
watchCards: true # reload the catalog when the card directory changes
|
|
416
568
|
```
|
|
417
569
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
technical enough.
|
|
570
|
+
The technical-token check depends on no configuration: it always runs and is
|
|
571
|
+
free. The retired `factCheck` key is ignored, so a profile still carrying it
|
|
572
|
+
changes nothing.
|
|
422
573
|
|
|
423
574
|
---
|
|
424
575
|
|
|
@@ -430,8 +581,8 @@ refused). Mounted under `/persona-forge`.
|
|
|
430
581
|
|
|
431
582
|
| Route | Body | Returns |
|
|
432
583
|
|---|---|---|
|
|
433
|
-
| `/persona-forge/cards` | `{}` | `{ cards, diagnostics, directory, sendMode,
|
|
434
|
-
| `/persona-forge/rewrite` | `{ cardId, text, sessionId?, intensity?, mode?, fidelity
|
|
584
|
+
| `/persona-forge/cards` | `{}` | `{ cards, diagnostics, directory, sendMode, draftModel }` |
|
|
585
|
+
| `/persona-forge/rewrite` | `{ cardId, text, sessionId?, intensity?, mode?, fidelity? }` | `{ text, provider, model, mode, cardId, fidelity, intensity, elapsedMs, facts }` |
|
|
435
586
|
| `/persona-forge/cards/save` | `{ card }` | `{ id, path }` |
|
|
436
587
|
| `/persona-forge/cards/delete` | `{ id }` | `{ removed }` |
|
|
437
588
|
| `/persona-forge/cards/reset` | `{ id }` | `{ id }` — replaces the user card with the bundled one |
|
|
@@ -475,7 +626,8 @@ npm run check # both
|
|
|
475
626
|
`check.mjs` needs no harness and no model. It covers the built-in YAML reader
|
|
476
627
|
(including its refusals and dump/parse round trips), card normalization, the
|
|
477
628
|
bundled cards' fact preservation, prompt construction, output normalization,
|
|
478
|
-
the fact
|
|
629
|
+
the local fact comparison, route resolution order, the send-gesture decision,
|
|
630
|
+
and client-bundle syntax.
|
|
479
631
|
|
|
480
632
|
`host-check.mjs` mounts the real plugin entry on a stub Cordis context and
|
|
481
633
|
drives the real HTTP routes over a real socket, with a stubbed `llm` service.
|
|
@@ -506,7 +658,7 @@ naming the line.
|
|
|
506
658
|
| `lib/index.js` | Host entry: card store, directory watcher, route registration |
|
|
507
659
|
| `lib/store.js` | Card loading, normalization, save/delete |
|
|
508
660
|
| `lib/yaml.js` | The built-in YAML subset reader and writer |
|
|
509
|
-
| `lib/prompts.js` | Rewrite system prompt, draft framing,
|
|
661
|
+
| `lib/prompts.js` | Rewrite system prompt, draft framing, AI-draft prompt |
|
|
510
662
|
| `lib/rewrite.js` | The model calls and output normalization |
|
|
511
663
|
| `lib/routes.js` | HTTP routes and session-model resolution |
|
|
512
664
|
| `lib/loopback.js` | The loopback trust fence |
|