@matamt-dbg/dsh-studio 0.3.0 → 0.4.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.
@@ -0,0 +1,267 @@
1
+ # Pixie Gate guide
2
+
3
+ English | [한국어](pixie-gate.ko.md)
4
+
5
+ Pixie Gate lets the **Pixie model read, judge, and rework content** at a set moment in an agent's work, then sends the result to the agent or to you. Rules and external jobs belong to DSH command hooks (Claude Code and Codex hooks); Pixie Gate is the layer above them for work that needs a model's judgment. It works on the original text alone, without any hook.
6
+
7
+ - [Create a gate](#create-a-gate)
8
+ - [When, and how results apply](#when-and-how-results-apply)
9
+ - [Advanced options](#advanced-options)
10
+ - [Pixie hook scripts](#pixie-hook-scripts)
11
+ - [The pixie helper](#the-pixie-helper)
12
+ - [Decision engine](#decision-engine)
13
+ - [Example scripts](#example-scripts)
14
+ - [Agent skill](#agent-skill)
15
+ - [Chat notes and per-session switches](#chat-notes-and-per-session-switches)
16
+ - [Run records](#run-records)
17
+ - [Limits and troubleshooting](#limits-and-troubleshooting)
18
+
19
+ ## Create a gate
20
+
21
+ 1. In **Studio → Pixie → Settings → Model**, choose the Pixie model. Gate tasks and `pixie ask` use it; `pixie judge` follows the [decision engine](#decision-engine) setting.
22
+ 2. In **Gates → Gate composition**, press **New gate** and pick a template. Each point has one representative template (instruction format check, agent message protocol, block risky commands, digest long tool results, verify the final answer); the blank gate is last. The switch on each card turns the gate on or off everywhere.
23
+ 3. Set **When** and **What Pixie does**. Write the task in plain words: whether to pass or stop, what to replace or add, and what note to show only to you.
24
+ 4. Put a sample in **Try it** and run it. The configured Pixie model really answers; nothing is recorded or sent to a session.
25
+ 5. Press **Apply**, then **Save** at the top of the page. Only saved gates apply to runs.
26
+ 6. **Gates → Scope** sets the script folder at the top and then lists the presets made in Studio. Gates not yet added to a Studio preset are collected at the bottom. Use **Add gate** on a preset to attach a gate, and the row switch to turn it on or off **for that preset only**. A gate can be attached to several presets; one preset's switch never affects another. Save to apply. A gate runs only for agents using those presets.
27
+
28
+ Only one enabled gate per preset and **When** is allowed (the page warns, and saving is refused). Saved definitions live in `<profile>/studio-data/pixie-gate/definitions.json`.
29
+
30
+ ## When, and how results apply
31
+
32
+ Pixie answers with five fields, all optional. Without a verdict the gate passes.
33
+
34
+ | Field | Meaning |
35
+ | --- | --- |
36
+ | Verdict | `pass` or `stop` |
37
+ | Reason | Why it stopped; the correction to make |
38
+ | Replacement | Text that replaces the target |
39
+ | Addition | Text sent along with the target |
40
+ | Note | Shown only to you |
41
+
42
+ Each point applies them in a fixed way. Output a point cannot apply becomes a note, not an error.
43
+
44
+ | When | Stop + reason | Replacement | Addition | Note |
45
+ | --- | --- | --- | --- | --- |
46
+ | You send an instruction | Input rejected; the run record keeps a restore card | Message replaced (optional confirmation) | Sent along | Recorded |
47
+ | Agents message each other | Input rejected | Message replaced | Sent along | Recorded |
48
+ | Before a tool runs | Execution denied (the reason reaches the agent) | As a note | As a note | Recorded |
49
+ | A tool result arrives | Result blocked (the reason reaches the agent) | Result replaced (not for structured results carrying a value) | Sent along | Recorded |
50
+ | The agent finishes its answer | Asked to redo it with the reason (per-turn limit) | As a note | As a note | Recorded |
51
+
52
+ When the verdict is stop, the replacement and addition never reach the main model. At message points the replacement becomes the rejection's suggestion and the addition becomes a note. Input or tools another hook already rejected do not run the gate.
53
+
54
+ ## Advanced options
55
+
56
+ | Option | Default | Description |
57
+ | --- | --- | --- |
58
+ | Pixie hook script | None | A script run before the task. See [below](#pixie-hook-scripts) |
59
+ | Confirm before replacing | Off | Stops a real replacement and shows it as a suggestion (message points) |
60
+ | On error | Pass | Pass or stop on model or script errors and timeouts |
61
+ | Target agents | Root (child for agent messages) | Root, child, or any |
62
+ | Time limit | 60 s | Script, helper, and model calls together |
63
+ | Redo limit | 1 | Corrections per turn at the answer-end point |
64
+
65
+ ## Pixie hook scripts
66
+
67
+ Build flows the two fields cannot express — only certain tools, translate → judge → retranslate loops, external measurements, concluding from a judgment alone — as a script. Studio does not build features one by one; it gives scripts the means.
68
+
69
+ - **Location:** the default is `<profile>/studio-data/pixie-gate/commands/`; change it under **Gates → Scope → Script folder** to another absolute or `~/…` path, and use **Open folder** to show it in Finder or Explorer (when DSH runs on your desktop). Leave it empty to restore the default; the folder is not created for you. Only executable files (`chmod +x`) in that folder can be chosen. Subfolders, links pointing outside the folder, and names containing `..` are excluded. Press **Refresh list** after adding a file.
70
+ - **Supported environments:** available only when DSH runs with a bash profile (macOS and Linux). Windows is not supported yet; where scripts are unsupported the gate does not run them and applies its error policy.
71
+ - **Working directory and sandbox:** scripts run in the session working directory through the DSH shell service, under the session's sandbox policy. A read-only session cannot write files.
72
+ - **Trials** do not run the script because no session policy is known. Check it in a real session.
73
+
74
+ ### Input, output, exit codes
75
+
76
+ | Item | Rule |
77
+ | --- | --- |
78
+ | stdin | The target text (instruction, message, tool arguments JSON, tool result, final answer) |
79
+ | stdout | Use it in the task as `{{hooks.<name>.text}}`; only boundary newlines are removed; up to 256 KB |
80
+ | stdout is a JSON object | `{{hooks.<name>.data}}` holds that JSON; otherwise it is empty |
81
+ | exit 0 | Continue: Pixie runs the task |
82
+ | exit 10 | Skip this gate: the original flow continues, no model call |
83
+ | exit 11 | Use stdout as the gate output: no Pixie call. See below |
84
+ | Other, or timeout | Error: the error policy applies |
85
+
86
+ `<name>` is the file name without its last extension (`measure-subtitle.sh` → `measure-subtitle`). A task using an undefined variable cannot be saved.
87
+
88
+ **Exit 11 — the script concludes.** stdout must be the same JSON object Pixie returns, with optional `verdict` (`pass` or `stop`), `reason`, `replace`, `append`, and `note`. The [point rules](#when-and-how-results-apply) apply unchanged, and the run record shows **Concluded by** `Hook script`. Non-JSON output or an unknown field follows the error policy.
89
+
90
+ ```bash
91
+ printf '{"verdict":"stop","reason":"The form has no title line."}'; exit 11
92
+ ```
93
+
94
+ If the script always ends with exit 10 or 11, the **task** can stay empty. A gate with an empty task fails when its script exits 0.
95
+
96
+ ### Environment
97
+
98
+ | Variable | Value |
99
+ | --- | --- |
100
+ | `PIXIE_POINT` | `user-message`, `agent-message`, `tool-before`, `tool-after`, `turn-end` |
101
+ | `PIXIE_TOOL_NAME`, `PIXIE_TOOL_ARGS` | Tool name and arguments JSON at tool points |
102
+ | `PIXIE_AGENT` | `root` or `child` |
103
+ | `PIXIE_SESSION_ID`, `PIXIE_TURN` | Session ID and turn number |
104
+ | `PIXIE_GATE_NAME` | Gate name |
105
+ | `PIXIE_URL`, `PIXIE_TOKEN` | For the `pixie` helper; issued per run and revoked when the script ends |
106
+
107
+ ## The pixie helper
108
+
109
+ Inside a script, the `pixie` command calls the Pixie model. It is first on the script's `PATH` and needs curl.
110
+
111
+ ```sh
112
+ pixie ask "<instruction>" [--input]
113
+ pixie judge [--type bool|select|score] --question "<question>" [type arguments] [--json] [--input]
114
+ ```
115
+
116
+ - With `--input` the helper reads its input from stdin; otherwise it uses the gate target.
117
+ - `ask` prints the answer and exits 0, using the Pixie model.
118
+ - `judge` judges with the [decision engine](#decision-engine); types and output follow the table there.
119
+ - Usage, token, limit, and model errors exit 2 with a message on stderr. A failed helper call never decides the gate; the script's exit code does.
120
+ - Limits: 20 calls and 256 KB per request for each run. Calls follow the gate time limit and cancellation; their usage is added to the gate and listed under **Helper calls** in the run record.
121
+ - A token reaches only that run's ask and judge. The helper uses a Studio route on the DSH web server, so it is unavailable without one (for example, headless).
122
+
123
+ ## Decision engine
124
+
125
+ `pixie judge` uses the engine chosen in **Studio → Pixie → Gates → Decision engine**. A judgment runs only when a script asks for one, and the script decides what to do with the result.
126
+
127
+ | Engine | Description |
128
+ | --- | --- |
129
+ | LLM (default) | The judge model (the Pixie model when unset) answers in the Jev format. The judge system prompt can be changed |
130
+ | Jev | [TypeSafe Jev](https://docs.typesafe.ai/api) answers through its API. The model defaults to `jev-latest`; once thresholds are tuned, pin a version such as `jev-1.13.0`. **Gate input is sent to TypeSafe** |
131
+
132
+ **Jev API key:** paste it on the decision engine page and press **Save key**. It is stored in DSH credentials as `TYPESAFE_API_KEY` and never shown again. A `TYPESAFE_API_KEY` from the environment or `.env` is used instead and cannot be changed on the page. Without a valid key, `pixie judge` fails with exit 2.
133
+
134
+ | `--type` | Arguments | stdout | exit |
135
+ | --- | --- | --- | --- |
136
+ | `bool` (default) | `--threshold` (default 0.5); optional `--true "<what yes means>"`, `--false "<what no means>"` | "yes" probability | 0 at or above the threshold, 1 below |
137
+ | `select` | Two or more `--option name="description"` | The chosen option name | 0 |
138
+ | `score` | 2–10 `--level "description"`, lowest first | The score (from 0, may be fractional) | 0 |
139
+
140
+ - `--json` prints one JSON line `{"type","label","answer","engine"}`. `label` is `yes`/`no` for bool, the option name for select, and the nearest level number for score; `answer` holds the probabilities and confidence.
141
+ - Write the full judgment in `--question`; question IDs are not sent to the model. When the input has several parts, wrap them in JSON and name them in the question, such as `` `source` ``.
142
+ - A judgment error stays an error: it never becomes "no" or a low score, and exits 2.
143
+ - The previous `pixie judge --question … --threshold …` still works (`--type bool`).
144
+
145
+ ### The `judge` agent tool
146
+
147
+ The same decision engine is also an agent tool, `judge`. It is in Studio Master, and you can pick it in the preset editor's tool list. The built-in Optimized preset does not include it.
148
+
149
+ - Input is the Jev request shape as is: `{ state, questions: { <id>: { type, instructions, criteria } } }`, with the bool (`noul`), select (`choice`), and score types above.
150
+ - Output is per-question `answers` (probabilities and confidence), the engine used (`llm` or `jev`), and usage.
151
+ - It judges and never rewrites text. Use it to rank, filter, or verify, and let the agent do the editing (for example: score locale strings, rewrite only the low ones, judge again).
152
+ - A failed judgment comes back as a tool error, including when no engine is set or the Jev key is missing.
153
+
154
+ ## Example scripts
155
+
156
+ **Tool filter** (`only-search-tools.sh`, when a tool result arrives): run the gate only for long search results.
157
+
158
+ ```bash
159
+ #!/bin/bash
160
+ case "$PIXIE_TOOL_NAME" in grep|glob|web_search) ;; *) exit 10 ;; esac
161
+ size=$(wc -c)
162
+ [ "$size" -gt 4000 ] || exit 10
163
+ echo "$size"
164
+ ```
165
+
166
+ **Subtitle measurement** (`measure-subtitle.sh`, when you send an instruction): pass the measurement as JSON.
167
+
168
+ ```bash
169
+ #!/bin/bash
170
+ text=$(cat)
171
+ lines=$(printf '%s' "$text" | grep -c -- '-->' || true)
172
+ printf '{"cues":%d,"bytes":%d}\n' "$lines" "${#text}"
173
+ ```
174
+
175
+ Task: `Measured: {{hooks.measure-subtitle.data}}` …
176
+
177
+ **Translation check** (`translate-check.sh`, when the agent finishes its answer): if the answer is already Korean, one judgment ends it (exit 10); otherwise Pixie translates it and the decision engine judges faithfulness against the source. No Pixie task is written; exit 11 leaves the note directly, and the note appears [under the answer in the chat](#chat-notes-and-per-session-switches). If neither attempt passes, the last translation is kept with a `not verified` label (`충실도 미확인`). Helper errors (exit 2) become exit 1 so the error policy applies. Requires `jq` (included with macOS).
178
+
179
+ ```bash
180
+ #!/bin/bash
181
+ source=$(cat)
182
+ printf '%s' "$source" | pixie judge --question "Is the prose of this text written in Korean? Ignore code blocks, file paths, identifiers and command output." --threshold 0.8 --input >/dev/null
183
+ status=$?
184
+ [ "$status" -eq 0 ] && exit 10
185
+ [ "$status" -eq 2 ] && exit 1
186
+ for _ in 1 2; do
187
+ draft=$(printf '%s' "$source" | pixie ask "Translate this agent answer into natural Korean. Keep code blocks, file paths, identifiers, commands and numbers unchanged. Keep the Markdown structure. Output only the translation." --input) || exit 1
188
+ if jq -n --arg s "$source" --arg t "$draft" '{source:$s, translation:$t}' \
189
+ | pixie judge --question "Does \`translation\` keep every condition, number, negation and code element of \`source\`?" --threshold 0.7 --input >/dev/null; then
190
+ jq -n --arg t "$draft" '{note: ("[한국어 번역]\n" + $t)}'; exit 11
191
+ else
192
+ status=$?
193
+ [ "$status" -eq 2 ] && exit 1
194
+ fi
195
+ done
196
+ jq -n --arg t "$draft" '{note: ("[한국어 번역 — 충실도 미확인]\n" + $t)}'
197
+ exit 11
198
+ ```
199
+
200
+ An answer that mixes Korean and English gets a middle Korean probability, so it is translated and may score low on faithfulness. Lower the first threshold (0.8) to skip mixed answers.
201
+
202
+ **Completion claim audit** (`claim-check.sh`, when the agent finishes its answer): judges with select whether the answer's test-pass claim matches the last recorded run. A contradiction asks for a redo, missing evidence leaves a note, and low confidence hands over to Pixie with exit 0. Adapt the run record file (`.last-test-run`) to your project.
203
+
204
+ ```bash
205
+ #!/bin/bash
206
+ answer=$(cat)
207
+ evidence=$(cat .last-test-run 2>/dev/null || echo "no recorded test run")
208
+ result=$(jq -n --arg a "$answer" --arg e "$evidence" '{answer:$a, evidence:$e}' | pixie judge --type select --json --input \
209
+ --question "Is the claim in \`answer\` that tests passed supported by \`evidence\`?" \
210
+ --option supported="evidence shows the claimed tests ran and passed, or answer makes no test claim" \
211
+ --option contradicted="evidence shows a failure or a different run" \
212
+ --option missing="answer claims tests passed but evidence has no run") || exit 1
213
+ case "$(jq -r .label <<<"$result")" in
214
+ supported) exit 10 ;;
215
+ contradicted) printf '{"verdict":"stop","reason":"The test results contradict the claim. Check the actual results and report again."}'; exit 11 ;;
216
+ missing) [ "$(jq '.answer.confidence < 0.6' <<<"$result")" = true ] && { printf '%s' "$result"; exit 0; }
217
+ printf '{"note":"No recorded test run."}'; exit 11 ;;
218
+ esac
219
+ ```
220
+
221
+ Task for a gate using this script (runs only on low confidence): `Read {{hooks.claim-check.data}}; stop with a reason if the test claim is unsupported.`
222
+
223
+ **Changed files** (`list-changed-files.sh`, when the agent finishes its answer): report git changes in the working directory.
224
+
225
+ ```bash
226
+ #!/bin/bash
227
+ git status --porcelain 2>/dev/null | head -50
228
+ ```
229
+
230
+ ## Agent skill
231
+
232
+ On start, Studio installs a skill with this guide and the hook rules into `<DSH home>/skills/studio-pixie-hook-guide/` (`~/.dsh/skills/` by default). Ask an agent something like "build a Pixie gate that checks translations" and it reads the skill to help you choose the point, write the script, use `pixie judge`, and follow the exit 0/10/11 rules.
233
+
234
+ - It holds `SKILL.md` (the rules) and `guide.md` (this guide).
235
+ - Updating Studio updates the skill. Files you edited are never overwritten; to get the Studio version back, delete that file and restart DSH.
236
+
237
+ ## Chat notes and per-session switches
238
+
239
+ **Chat notes:** when a hook script at the turn-end point concludes with a note (exit 11), for example a translation, the note appears as a block right under that turn's answer.
240
+
241
+ - If the note's first line starts with a bracketed label such as `[한국어 번역]`, the label becomes the block title. A label containing `not verified` (or `미확인`) gets a **not verified** badge.
242
+ - The body renders as Markdown. The block offers **Hide**, **Open in Pixie tab**, and **Turn off in this session**.
243
+ - It appears after the script finishes; there is no progress indicator. Skipped turns (exit 10), turns Pixie concluded, and turns without a note get no block. If the gate ran more than once in a turn, only the last note shows.
244
+ - The original answer stays as it is; it cannot be collapsed or replaced.
245
+
246
+ **Per-session switches:** at the top of **Pixie** tab → **Gates**, **Gates in this session** lists every gate that applies to this session's preset with a switch that turns it off for this session only. **Turn off in this session** on a chat block is the same switch.
247
+
248
+ - A gate switched off does not run at any point in this session: no script, Pixie, or decision engine call, and no record. It applies from the next message; no restart is needed.
249
+ - Gate definitions, preset attachments, and other sessions do not change. A new session starts with the preset's settings.
250
+ - The list shows gates that are switched on, attached to this preset, and not switched off for it.
251
+
252
+ ## Run records
253
+
254
+ The gate records in the session's right-side **Pixie** tab list each run. The detail shows the action actually applied (replaced, appended, rejected, blocked, steered, none), who concluded (Pixie, hook script, skipped by hook), the five output fields, token usage, original and final text, notes, and helper calls. Helper calls also show each `pixie judge` type, chosen value, engine, and confidence. When a script concluded the run, the output section is titled **Script output**. For a rejected input, **Edit and send** puts the suggestion (or the original) into the composer.
255
+
256
+ ## Limits and troubleshooting
257
+
258
+ - **A gate does not run.** Check that it is on, has a preset, and is saved; that the session runs that preset; that the target agents (root or child) match; and that it is not off in **Gates in this session**. Without a Pixie model the error policy applies.
259
+ - **`hook-script-unsupported`** means no bash executor is available.
260
+ - **`Session sandbox policy and cwd are required`** means the session policy is unknown.
261
+ - **`pixie: helper is not available`** means there is no web server, or the command ran outside a script run.
262
+ - **`pixie: HTTP 401`** means the run already ended or the token belongs to another run. **429** is the call limit; **413** is the request size limit.
263
+ - **`Jev API key is not configured`** means the decision engine is Jev and `TYPESAFE_API_KEY` is missing. **`Jev request failed: HTTP 401`** means a wrong key; **422** means a malformed question.
264
+ - **Saving the key reports an empty `refs:` line.** Change the bare `refs:` line in the DSH credentials file (`.credentials.yaml` in the DSH home) to `refs: {}` and save again. DSH cannot add a key under a `refs:` line with no value.
265
+ - **`Hook script exit 11 needs a gate output JSON`** means the stdout of an exit 11 is not gate output JSON.
266
+ - Sandboxes that block local network access can make helper calls fail.
267
+ - Background tasks (pre-compaction, file pre-indexing) are not supported yet.