@junghanacs/entwurf 0.12.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/AGENTS.md +240 -0
- package/BASELINE.md +227 -0
- package/CHANGELOG.md +1210 -0
- package/CONTRIBUTING.md +63 -0
- package/DELIVERY.md +209 -0
- package/LICENSE +21 -0
- package/README.md +504 -0
- package/VERIFY.md +260 -0
- package/demo/README.md +188 -0
- package/demo/demo-baseline.sh +156 -0
- package/demo/demo.sh +183 -0
- package/docs/assets/entwurf-demo.gif +0 -0
- package/docs/assets/entwurf-doomemacs.gif +0 -0
- package/docs/assets/entwurf-entwurf.gif +0 -0
- package/docs/assets/entwurf-hero.jpg +0 -0
- package/docs/setup-clean-host.md +305 -0
- package/mcp/entwurf-bridge/src/index.ts +513 -0
- package/mcp/entwurf-bridge/start.sh +25 -0
- package/mcp/entwurf-bridge/test.sh +54 -0
- package/mcp/tsconfig.json +29 -0
- package/package.json +130 -0
- package/pi/entwurf-capabilities.json +9 -0
- package/pi/entwurf-targets.json +20 -0
- package/pi/meta-bridge/.claude-plugin/marketplace.json +12 -0
- package/pi/meta-bridge/entwurf-meta-receive/.claude-plugin/plugin.json +5 -0
- package/pi/meta-bridge/entwurf-meta-receive/hooks/hooks.json +50 -0
- package/pi/meta-bridge/entwurf-meta-receive/scripts/doorbell.sh +54 -0
- package/pi/settings.reference.json +43 -0
- package/pi/skill-plugin-example/.claude-plugin/plugin.json +4 -0
- package/pi/skill-plugin-example/skills/hello/SKILL.md +18 -0
- package/pi-extensions/acp-provider.ts +63 -0
- package/pi-extensions/entwurf-control.ts +1692 -0
- package/pi-extensions/lib/acp/acp-client.ts +90 -0
- package/pi-extensions/lib/acp/augment.ts +238 -0
- package/pi-extensions/lib/acp/backend-adapter.ts +319 -0
- package/pi-extensions/lib/acp/backend.ts +873 -0
- package/pi-extensions/lib/acp/config.ts +552 -0
- package/pi-extensions/lib/acp/context.ts +177 -0
- package/pi-extensions/lib/acp/engraving.ts +123 -0
- package/pi-extensions/lib/acp/event-mapper.ts +339 -0
- package/pi-extensions/lib/acp/models.ts +102 -0
- package/pi-extensions/lib/acp/overlay.ts +220 -0
- package/pi-extensions/lib/acp/prompts/engraving.md +1 -0
- package/pi-extensions/lib/acp/session-store.ts +418 -0
- package/pi-extensions/lib/acp/tool-surface.ts +184 -0
- package/pi-extensions/lib/entwurf-control-rpc.ts +208 -0
- package/pi-extensions/lib/entwurf-core.ts +2033 -0
- package/pi-extensions/lib/entwurf-deliverability.ts +123 -0
- package/pi-extensions/lib/entwurf-fact-provider.ts +158 -0
- package/pi-extensions/lib/entwurf-facts.ts +251 -0
- package/pi-extensions/lib/entwurf-mailbox-guard.ts +100 -0
- package/pi-extensions/lib/entwurf-peers-render.ts +154 -0
- package/pi-extensions/lib/entwurf-preflight.ts +247 -0
- package/pi-extensions/lib/entwurf-resume-args.ts +88 -0
- package/pi-extensions/lib/entwurf-self-address.ts +117 -0
- package/pi-extensions/lib/entwurf-v2-contract.ts +427 -0
- package/pi-extensions/lib/entwurf-v2-decider.ts +441 -0
- package/pi-extensions/lib/entwurf-v2-lock.ts +412 -0
- package/pi-extensions/lib/entwurf-v2-mailbox.ts +87 -0
- package/pi-extensions/lib/entwurf-v2-production.ts +326 -0
- package/pi-extensions/lib/entwurf-v2-release.ts +149 -0
- package/pi-extensions/lib/entwurf-v2-resume-marker.ts +34 -0
- package/pi-extensions/lib/entwurf-v2-runner.ts +196 -0
- package/pi-extensions/lib/entwurf-v2-send-fallback.ts +166 -0
- package/pi-extensions/lib/entwurf-v2-send.ts +271 -0
- package/pi-extensions/lib/entwurf-v2-spawn-production.ts +337 -0
- package/pi-extensions/lib/entwurf-v2-spawn.ts +323 -0
- package/pi-extensions/lib/entwurf-v2-surface.ts +205 -0
- package/pi-extensions/lib/meta-mailbox-body.ts +80 -0
- package/pi-extensions/lib/meta-session.ts +1951 -0
- package/pi-extensions/lib/project-trust-handler.ts +154 -0
- package/pi-extensions/lib/session-id.js +57 -0
- package/pi-extensions/lib/socket-discovery.ts +346 -0
- package/pi-extensions/lib/socket-probe.ts +92 -0
- package/pi-extensions/meta-bridge-hook.ts +250 -0
- package/pi-extensions/model-lock.ts +235 -0
- package/prompts/engraving.md +27 -0
- package/protocol.js +31 -0
- package/run.sh +2832 -0
- package/scripts/check-acp-backend-preflight.ts +130 -0
- package/scripts/check-acp-carrier-augment.ts +297 -0
- package/scripts/check-acp-config.ts +322 -0
- package/scripts/check-acp-event-mapper.ts +253 -0
- package/scripts/check-acp-overlay.ts +154 -0
- package/scripts/check-acp-prompt-builder.ts +191 -0
- package/scripts/check-acp-provider-surface.ts +159 -0
- package/scripts/check-acp-sdk-surface.ts +211 -0
- package/scripts/check-acp-session-reuse.ts +756 -0
- package/scripts/check-acp-session-store.ts +387 -0
- package/scripts/check-acp-tool-surface.ts +159 -0
- package/scripts/check-entwurf-bridge-boot.ts +199 -0
- package/scripts/check-entwurf-capabilities.ts +123 -0
- package/scripts/check-entwurf-control-rpc.ts +187 -0
- package/scripts/check-entwurf-deliverability.ts +158 -0
- package/scripts/check-entwurf-fact-provider.ts +316 -0
- package/scripts/check-entwurf-facts.ts +358 -0
- package/scripts/check-entwurf-mailbox-guard.ts +264 -0
- package/scripts/check-entwurf-peers-surface.ts +235 -0
- package/scripts/check-entwurf-resume-args.ts +149 -0
- package/scripts/check-entwurf-self-address.ts +209 -0
- package/scripts/check-entwurf-session-identity.ts +703 -0
- package/scripts/check-entwurf-v2-contract.ts +536 -0
- package/scripts/check-entwurf-v2-decider.ts +795 -0
- package/scripts/check-entwurf-v2-lock.ts +368 -0
- package/scripts/check-entwurf-v2-mailbox.ts +228 -0
- package/scripts/check-entwurf-v2-matrix.ts +437 -0
- package/scripts/check-entwurf-v2-production.ts +406 -0
- package/scripts/check-entwurf-v2-release.ts +245 -0
- package/scripts/check-entwurf-v2-runner.ts +452 -0
- package/scripts/check-entwurf-v2-send-fallback.ts +371 -0
- package/scripts/check-entwurf-v2-send.ts +454 -0
- package/scripts/check-entwurf-v2-spawn-production.ts +452 -0
- package/scripts/check-entwurf-v2-spawn.ts +398 -0
- package/scripts/check-entwurf-v2-surface.ts +352 -0
- package/scripts/check-keyset-overlap.py +120 -0
- package/scripts/check-mailbox-receipt-state.ts +170 -0
- package/scripts/check-meta-capability-source.ts +112 -0
- package/scripts/check-meta-dual-consumers.ts +154 -0
- package/scripts/check-meta-dual-read.ts +158 -0
- package/scripts/check-meta-listing.ts +138 -0
- package/scripts/check-meta-mailbox-state-write.ts +135 -0
- package/scripts/check-meta-migration.ts +212 -0
- package/scripts/check-meta-receiver-marker.ts +185 -0
- package/scripts/check-meta-record-v2.ts +191 -0
- package/scripts/check-meta-session.ts +673 -0
- package/scripts/check-model-lock.ts +408 -0
- package/scripts/check-package-source-routing.ts +253 -0
- package/scripts/check-pi-preflight.ts +304 -0
- package/scripts/check-project-trust-handler.ts +265 -0
- package/scripts/check-shell-quote.ts +121 -0
- package/scripts/check-socket-discovery.ts +428 -0
- package/scripts/check-socket-probe.ts +106 -0
- package/scripts/fixtures/probe-mcp-server.ts +33 -0
- package/scripts/gnew-rpc-drive.ts +211 -0
- package/scripts/lib/acp-child-cleanup.ts +116 -0
- package/scripts/meta-bridge-doctor.sh +315 -0
- package/scripts/meta-bridge-hook-log.sh +26 -0
- package/scripts/meta-bridge-install.sh +135 -0
- package/scripts/meta-bridge-prune.ts +199 -0
- package/scripts/meta-bridge-state.py +549 -0
- package/scripts/meta-bridge-statusline.sh +192 -0
- package/scripts/meta-bridge-store-doctor.ts +64 -0
- package/scripts/meta-bridge-uninstall.sh +39 -0
- package/scripts/new-session-id.ts +25 -0
- package/scripts/postinstall-chmod.cjs +58 -0
- package/scripts/raw-async-delivery/README.md +258 -0
- package/scripts/raw-async-delivery/cc-enqueue-addressed.sh +35 -0
- package/scripts/raw-async-delivery/cc-mailbox-rewake.sh +38 -0
- package/scripts/raw-async-delivery/cc-watch-filechanged.sh +19 -0
- package/scripts/raw-async-delivery/cc-watch-sessionstart.sh +15 -0
- package/scripts/raw-async-delivery/codex-local-appserver.sh +39 -0
- package/scripts/raw-async-delivery/plugin-entwurf-receive/.claude-plugin/plugin.json +5 -0
- package/scripts/raw-async-delivery/plugin-entwurf-receive/hooks/hooks.json +28 -0
- package/scripts/raw-async-delivery/plugin-entwurf-receive/scripts/watch-filechanged.sh +28 -0
- package/scripts/raw-async-delivery/plugin-entwurf-receive/scripts/watch-sessionstart.sh +27 -0
- package/scripts/raw-async-delivery/raw-agy-send.sh +29 -0
- package/scripts/raw-async-delivery/raw-claude-enqueue.sh +30 -0
- package/scripts/raw-async-delivery/raw-codex-ws-turn-start.py +164 -0
- package/scripts/raw-async-delivery/repro-addressed-routing.sh +96 -0
- package/scripts/raw-async-delivery/repro-plugin-idle-wake.sh +104 -0
- package/scripts/resolve-acp-bridge.ts +25 -0
- package/scripts/smoke-acp-bundled-mcp-live.ts +292 -0
- package/scripts/smoke-acp-carrier-augment-live.ts +192 -0
- package/scripts/smoke-acp-mcp-live.ts +129 -0
- package/scripts/smoke-acp-memory-containment-live.ts +389 -0
- package/scripts/smoke-acp-overlay-live.ts +314 -0
- package/scripts/smoke-acp-provider-live.ts +162 -0
- package/scripts/smoke-acp-raw-turn-live.ts +261 -0
- package/scripts/smoke-acp-session-reuse-live.ts +172 -0
- package/scripts/smoke-acp-skill-live.ts +144 -0
- package/scripts/smoke-acp-socket-citizen-live.ts +168 -0
- package/scripts/smoke-claude-native-resume-live.sh +198 -0
- package/scripts/smoke-entwurf-v2-matrix-live.ts +398 -0
- package/scripts/smoke-entwurf-v2-spawn-live.ts +175 -0
- package/scripts/smoke-entwurf-v2-spawn-resume-live.ts +428 -0
- package/scripts/smoke-meta-async-drift.sh +171 -0
- package/scripts/smoke-meta-honesty.sh +147 -0
- package/scripts/smoke-meta-install-state.sh +403 -0
- package/scripts/smoke-meta-keyset-guard.sh +111 -0
- package/scripts/smoke-meta-prune.sh +174 -0
- package/scripts/smoke-resident-garden-guard.sh +433 -0
- package/scripts/smoke-session-id-name.ts +187 -0
- package/scripts/tsconfig.json +34 -0
package/VERIFY.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# VERIFY.md
|
|
2
|
+
|
|
3
|
+
Agent-driven verification guide for `entwurf` (0.12.0 surface).
|
|
4
|
+
|
|
5
|
+
> **Current surface.** The live release surface is one bundled MCP server, `entwurf-bridge`, exposing four tools: `entwurf_v2`, `entwurf_peers`, `entwurf_self`, `entwurf_inbox_read`. The shipped ACP backend is **Claude**; Codex is pi-native by default (`ENTWURF_ACP_FOR_CODEX=1` opts a Codex target into ACP), and Gemini is a **non-goal/probe** on 0.12 — historical Gemini rows are kept for context, not as a current expectation. The 0.4.x `session-bridge` adapter, the 0.11.0 fat-bridge (`acp-bridge.ts` / `ensureBridgeSession`), and the v1 `entwurf` / `entwurf_resume` / `entwurf_send` verbs are **retired** — rows mentioning them survive in CHANGELOG/git as historical baseline, never as a runnable recipe.
|
|
6
|
+
|
|
7
|
+
This is a **working document, not a metrics document**. The deterministic and live gates carry the machine-checkable invariants; this file carries only what a gate cannot judge — the human/agent reading of *whether the bridge is honestly itself*. Where a former manual procedure is now a gate, it is named as a pointer rather than re-spelled as a runnable script.
|
|
8
|
+
|
|
9
|
+
VERIFY.md is the **agent-driven** surface; [BASELINE.md](./BASELINE.md) is the operator-driven one. One ACP-bridged model runs the checks against another and writes down what it sees — if the bridge is faithful, two replicants looking at the same mirror describe the mirror the same way. This is in-bridge cross-validation, not external evidence: verifier and subject share the same bridge, MCP servers, and overlay, so a uniform corruption of those would not surface here (that gap is what the L3+ rungs close).
|
|
10
|
+
|
|
11
|
+
## Evidence Levels
|
|
12
|
+
|
|
13
|
+
Every claim — and every History entry — sits on one of these rungs. Make the rung explicit so neither narrative nor reader overreaches.
|
|
14
|
+
|
|
15
|
+
> **Namespace note.** These `L0–L5` rungs measure *evidence quality* for bridge verification. Native async delivery has its own capability namespace `D0–D8` in [DELIVERY.md](./DELIVERY.md); operator-driven identity baseline uses `Q-L1..Q-L5` *surface-isolation layers* in [BASELINE.md](./BASELINE.md). Same letters, different axes — do not conflate "high-quality evidence" with "high delivery capability".
|
|
16
|
+
|
|
17
|
+
| Level | What it is | Closes | Does not close |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| **L0** | Narrative / self-report | Agent description of the system | Anything depending on actual behaviour |
|
|
20
|
+
| **L1** | Transcript cross-check | Two+ bridged identities agree on what they see | Echo-chamber risk (shared prompt/carrier) |
|
|
21
|
+
| **L2** | Objective MCP tool call | Real on-disk/on-socket payload through the bridge | Shared-implementation corruption |
|
|
22
|
+
| **L3** | On-disk/process/socket corroboration *outside* the bridge | Bridge claim ↔ `ls`/`pgrep`/`lsof`/session JSONL | Time-extended drift (auth, version, cache) |
|
|
23
|
+
| **L4** | Human or direct-native side-by-side | A person (or non-bridged direct path) reaches the same answer for matched prompts | Production-shape workload |
|
|
24
|
+
| **L5** | Long-haul soak | Bridge stays correct over hours-to-days incl. partial failure | Operational ceiling for now |
|
|
25
|
+
|
|
26
|
+
When you write a new entry, mark its rung. "L1 only" is honest; "L2 reached" is stronger but does not silently imply L3.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 0A. Execution Policy — Transparent Mode
|
|
31
|
+
|
|
32
|
+
Verification here is not a benchmark. In production we exchange short turns and stop immediately to isolate a cause before resuming when something looks off. This document records **verification intent (what we look at) and pass criteria (how to judge)**; the execution shape is the agent's choice as long as the criteria are met.
|
|
33
|
+
|
|
34
|
+
### The canonical floor — two entry points
|
|
35
|
+
|
|
36
|
+
- **Deterministic floor:** `pnpm check` — the full `check-*` gate set (~60 gates). Run first; it is the cheap, machine-checkable layer.
|
|
37
|
+
- **Live floor:** `LIVE=1 ./run.sh release-gate <scratch-project-dir>` — `pnpm check` + the v2-native live gates + the ACP plugin acceptance floor. It reports a **two-tier summary**:
|
|
38
|
+
- **MUST tier** (release-blocking — owns the exit code; "green" applies only here): `pnpm check`, `smoke-entwurf-v2-spawn-resume-live`, `smoke-entwurf-v2-matrix-live`, `check-bridge`, `smoke-session-id-name`, the resident-garden-guard negative/id-safety + `/gnew` zero-token half, and the `smoke-acp-*-live` ACP plugin smokes (socket-citizen / raw-turn / overlay / provider / session-reuse / carrier-augment / memory-containment / rgg / mcp / skill / bundled-mcp).
|
|
39
|
+
- **BEHAVIOR tier** (advisory, non-blocking): the resident-garden-guard positive (a model-in-loop `entwurf_self` turn). A BEHAVIOR FAIL is surfaced with its artifact path but **never blocks the cut**.
|
|
40
|
+
- LIVE-gated MUST steps honest-skip when `LIVE!=1`; a real cut needs `LIVE=1` with `SKIP=0`. A green MUST gate is **necessary, not sufficient** — GLG authorizes the cut.
|
|
41
|
+
|
|
42
|
+
> The authoritative per-cut counts live in BASELINE.md's HISTORY and CHANGELOG/git, not inline here (they drift against `run.sh`). Most recent recorded floor: **2026-06-27 — MUST 17/0/0 + BEHAVIOR 1/0**.
|
|
43
|
+
|
|
44
|
+
### Verifying the two capabilities a gate cannot fully judge
|
|
45
|
+
|
|
46
|
+
- **Garden-id delivery:** discover a target with `entwurf_peers`, then `entwurf_v2` with the correct intent — `fire-and-forget` for a live/replyable or meta-session target, `owned-outcome` only to wake a dormant record-backed pi citizen. Picking the wrong intent is rejected, never auto-fixed.
|
|
47
|
+
- **ACP continuity:** a direct `pi --provider entwurf --model claude-sonnet-4-6` turn, or the `smoke-acp-session-reuse-live` gate (process-scoped reuse + recall). Multi-turn reuse is proven by that gate, not by any v1 resume tool.
|
|
48
|
+
|
|
49
|
+
### What NOT to do — bypassing the operational path
|
|
50
|
+
|
|
51
|
+
These bypass the very delegation logic under test; passing them proves nothing about production health.
|
|
52
|
+
|
|
53
|
+
- ✗ Minting session files directly (`mktemp …jsonl`) and feeding them to `pi --session`.
|
|
54
|
+
- ✗ Faking multi-turn by passing the same session file twice.
|
|
55
|
+
- ✗ Using pty/tmux `send-keys` keystrokes or transcript scraping as delivery evidence.
|
|
56
|
+
- ✗ Mimicking entwurf by recursively calling `pi` via `bash`.
|
|
57
|
+
|
|
58
|
+
The manual `pi --session` path is used only when (a) the entwurf path itself is broken and an isolated debug bypass is needed, or (b) a boundary check must hit a bridge internal directly.
|
|
59
|
+
|
|
60
|
+
### Operational principles
|
|
61
|
+
|
|
62
|
+
- Execute one command at a time (no `;`-chaining). Preserve full stdout/stderr at each step.
|
|
63
|
+
- On anything wrong, **stop and hold** — preserve session/cache/process state before proceeding.
|
|
64
|
+
|
|
65
|
+
### Wording — avoid safety-interpretation contamination
|
|
66
|
+
|
|
67
|
+
When injecting a fact for a continuity check, use **plaintext that does not trigger model safety interpretation**. Avoid `secret token`, `password`, `API key`, `credential`, and meta-directives like "do not leak" — such wording makes the model treat the prompt as an exfiltration attempt and refuse, which makes **continuity look broken even when it is alive** (this happened once with `test-token-123`, misdiagnosed as a delegation failure). Instead: `The password is owl → reply in one word → owl`; code names / colors / animal names. Do not mix continuity and safety-behavior verification in one prompt.
|
|
68
|
+
|
|
69
|
+
### bridge continuity vs semantic continuity
|
|
70
|
+
|
|
71
|
+
- **bridge continuity:** same `sessionKey` / same `acpSessionId` via in-memory reuse or persisted resume/load (bootstrap `path=reuse|resume|load`).
|
|
72
|
+
- **semantic continuity:** a fact from a prior turn is retrievable in a later turn.
|
|
73
|
+
|
|
74
|
+
Either can be alive while the other looks dead (the wording case above is bridge-alive / semantic-looks-dead). When in doubt, change the wording and retry once, and check the `[entwurf:bootstrap]` lines in bridge stderr. No automated smoke separates these yet.
|
|
75
|
+
|
|
76
|
+
## 0. Quality Criteria
|
|
77
|
+
|
|
78
|
+
The goal is not merely "invoke Claude Code." We want:
|
|
79
|
+
|
|
80
|
+
1. **Session continuity at the agent-shell level** — through ACP session resume/load/new, not re-throwing a text blob.
|
|
81
|
+
2. **Preservation of pi harness semantics** — pi session files / transcripts / memory pipeline stay a shared axis.
|
|
82
|
+
3. **restart-hygienic** — process-scoped reuse continues the same ACP session across turns inside a long-lived resident; persisted records are written/validated for the future resume-load lane, not the live continuity path today.
|
|
83
|
+
4. **Thin bridge** — no second harness built inside this repo.
|
|
84
|
+
5. **Explicit capability boundary** — pi custom tool / user MCP visibility is determined solely by `entwurfProvider.mcpServers`; no automatic `~/.mcp.json` loading.
|
|
85
|
+
6. **Operational hygiene** — no orphan subprocesses, no excess persisted session garbage.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 1. Setup
|
|
90
|
+
|
|
91
|
+
entwurf supports two install paths; both end in the same runtime state (a valid `.pi/settings.json` with `entwurfProvider.mcpServers` wired) and differ only in who owns the checkout.
|
|
92
|
+
|
|
93
|
+
| Path | Who | Shape |
|
|
94
|
+
|------|-----|-------|
|
|
95
|
+
| **A — Consumer** | end-user of pi | `pi install git:…` + one `run.sh install .` |
|
|
96
|
+
| **B — Developer** | contributor / first user | `git clone …` + `pi install ./` + `run.sh install …` |
|
|
97
|
+
|
|
98
|
+
### 1.1 Path A — consumer install
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
pi install git:github.com/junghan0611/entwurf # pi auto-clones + installs deps
|
|
102
|
+
cd /path/to/consumer-project
|
|
103
|
+
~/.pi/agent/git/github.com/junghan0611/entwurf/run.sh install . # wire bundled mcpServers
|
|
104
|
+
pi --list-models entwurf # curated model surface
|
|
105
|
+
pi --provider entwurf --model claude-sonnet-4-6 -p "reply with ok only" # one-turn smoke
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Expected: the package appears under pi's `User packages`; `install .` logs `added entwurfProvider.mcpServers.entwurf-bridge` + `updated <project>/.pi/settings.json`; the smoke returns a one-word reply (full bootstrap → ACP session → bridge → clean shutdown). Note: `~/.pi/agent/git/.../entwurf` is pi-managed — do not edit it (a `pi update` overwrites). Step 2 is still required after `pi install git:…`.
|
|
109
|
+
|
|
110
|
+
### 1.2 Path B — developer install
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
git clone https://github.com/junghan0611/entwurf /path/to/entwurf && cd $_
|
|
114
|
+
pnpm install # pnpm is the pinned packageManager
|
|
115
|
+
pi install ./
|
|
116
|
+
./run.sh install /path/to/consumer-project
|
|
117
|
+
pnpm check # full deterministic floor
|
|
118
|
+
pi --provider entwurf --model claude-sonnet-4-6 -p "reply with ok only"
|
|
119
|
+
LIVE=1 ./run.sh release-gate /path/to/consumer-project
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`install` is idempotent; user-authored `mcpServers.<name>` overrides survive a re-run (`preserved (user override: …)`). `run.sh remove <dir>` deletes only entries whose command matches the repo-authored launcher.
|
|
123
|
+
|
|
124
|
+
### 1.3 Setup shortcut + variables
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
export REPO_DIR=... # Path A: $HOME/.pi/agent/git/github.com/junghan0611/entwurf ; Path B: your clone
|
|
128
|
+
export PROJECT_DIR=/path/to/consumer-project
|
|
129
|
+
export CACHE_DIR=$HOME/.pi/agent/cache/entwurf/sessions
|
|
130
|
+
cd "$REPO_DIR" && ./run.sh setup "$PROJECT_DIR"
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`setup` runs `pnpm install` + `install` + meta-bridge (native harness) + the v2 install smoke; a green `setup` implies the settings.json wiring and install surface are healthy. The full live floor is still `LIVE=1 ./run.sh release-gate`.
|
|
134
|
+
|
|
135
|
+
### 1.4 Cross-install / cross-backend parity (optional, high-value)
|
|
136
|
+
|
|
137
|
+
Compare a fresh self-awareness report across axes: (1) same backend, different install path — answer must be path-invariant; (2) same backend, different machine — identical native tool list + MCP server/tool set; (3) different backend, same bridge — same harness id (`entwurf`) and MCP surface but **different** native tool surface (a Claude session reporting `apply_patch` as native, or normalized cross-backend tools, is a fail); (4) native pi routing vs ACP-bridged, same model — the native target reports **no `entwurf-bridge` MCP** (capability via pi's extension surface) while the ACP target reports it as the single MCP server. Honest "native: I cannot tell" hedging is PASS on the native side. Status: Claude axes 1–4 closed; Gemini is probe-only on 0.12.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 1A. Main Agent Evaluation — Is `entwurf` Claude strong enough?
|
|
142
|
+
|
|
143
|
+
Separate from continuity gates. Gates prove "sessions continue"; this questionnaire examines tool self-awareness / native tool usability / MCP-boundary awareness / long-turn focus / quality vs direct Claude Code. Run it against `entwurf/claude-sonnet-4-6` via a direct `pi --provider entwurf` turn (or a live ACP session); accumulate turns by re-prompting the same target.
|
|
144
|
+
|
|
145
|
+
### 1A.0 Two carrier surfaces — engraving vs pi-context-augment (load-bearing)
|
|
146
|
+
|
|
147
|
+
`entwurf` delivers identity-relevant text through **two structurally distinct surfaces**. Collapsing them into "the system prompt" is the most common verifier-side mistake. (BASELINE Q-B0/Q-L1 grade the same separation operator-side.)
|
|
148
|
+
|
|
149
|
+
| Surface | Source | Delivery shape | Default content |
|
|
150
|
+
|---|---|---|---|
|
|
151
|
+
| **Engraving carrier** | `pi-extensions/lib/acp/prompts/engraving.md` (or `ENTWURF_ACP_ENGRAVING_PATH`) | Claude `_meta.systemPrompt` — full-replacement identity slot | Operator-authored, optional opt-out; tiny non-empty by default on Claude ACP (replaces the `claude_code` preset + strips its auto-memory advertisement). Emptying the file is the opt-out. |
|
|
152
|
+
| **pi-context-augment** | `pi-extensions/lib/acp/augment.ts` (`enrichTaskWithProjectContext`) | First-user-message prepend (not the system slot) | Always populated on ACP-routed targets: (1) the bridge identity line, (2) `~/AGENTS.md` body, (3) the cwd repo's `AGENTS.md` in a `<project-context path="…">` block. |
|
|
153
|
+
|
|
154
|
+
Pass (carrier honesty): the subject distinguishes engraving from pi-context-augment by name or structure without prompting; on ACP targets confirms all three augment components arrived; may quote the engraving but must **not** attribute bridge identity / AGENTS / memory policy to it. Fail: attributes the bridge-identity narrative to the engraving carrier; claims the augment is empty on an ACP run; invents engraving content. Native pi exception: on native targets the bridge-identity line and `~/AGENTS.md` are not part of the augment — the PASS criterion is honesty about what arrived, not the three-component checklist.
|
|
155
|
+
|
|
156
|
+
### 1A.1 Layers
|
|
157
|
+
|
|
158
|
+
- **Layer 0 — self-awareness:** ask environment self-awareness / MCP visibility / upstream-instruction awareness, guessing prohibited. Pass: recognizes native tool family, says "I don't know" honestly, answers MCP visibility only as configured, describes upstream instruction type without reproducing internal prompts. Fail: claims a nonexistent tool, conflates pi-custom and native tools, hallucinates MCP visibility, or conflates the two carriers (§1A.0).
|
|
159
|
+
- **Layer 1 — native tool use:** throw file-reading / structure-analysis / regression-hunting tasks. Pass: Read/Edit/Bash/Grep/Glob selection is natural; no detour through MCP or recursive `pi`. Fail: strange detours for simple reads; speaks from memory without reading.
|
|
160
|
+
- **Layer 2 — MCP boundary:** by default the four v2 MCP tools are not visible (they appear only when `entwurf-bridge` is registered). Pass: says invisible tools are not visible; explains the native-vs-MCP boundary. Fail: pretends to use an unseen tool; mimics entwurf via recursive `pi`.
|
|
161
|
+
- **Layer 3 — focus across turns:** inject a fact, then accumulate turns mixing retrieval/exploration. Pass (post-0.4.1): after **8 turns** holds **3+ early facts** incl. **one verbatim string injected before turn 5**; no repeated exploration, no self-contradiction, no tool-strategy drift. Fail: forgets early reads; paraphrases instead of returning the verbatim string. Note: entwurf exposes no user-facing compaction; use the backend's `usage_update` footer as an overflow-risk signal (it follows the ACP backend's `used/size`, not pi's visible-transcript estimate).
|
|
162
|
+
- **Layer 4 — vs direct Claude Code:** requires a verifier holding **both** the `entwurf` and a direct path (human-in-loop, or both transport handles). Compare latency / native tool accuracy / detours / boundary confusion / quality around turns 10–15. Repeated tool confusion, long-turn forgetting, or boundary workarounds are a fail.
|
|
163
|
+
|
|
164
|
+
Interpretation: Layers 0–2 healthy → basic qualifications confirmed. Layer 3 weak → strengthen prompt shape + corroborate with bootstrap logs / process state / sentinel recall. Layer 4 much weaker than direct → revisit bridge handoff. This questionnaire does not replace gates.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 2. Manual judgement checks — what the gates cannot fully judge
|
|
169
|
+
|
|
170
|
+
The single-turn / multi-turn / cross-process / persistence-boundary / shutdown invariants that earlier editions hand-ran against the retired v1 verbs are now **deterministic or live gates**. Verify them through the gate, and reserve manual time for the human-judgement surfaces below.
|
|
171
|
+
|
|
172
|
+
| Invariant | Current gate (pointer) |
|
|
173
|
+
|---|---|
|
|
174
|
+
| Single-turn prompt extraction, SessionStart hook not mistaken for prompt | `smoke-acp-raw-turn-live`, `check-acp-prompt-builder` |
|
|
175
|
+
| Multi-turn continuity + recall (process-scoped reuse) | `smoke-acp-session-reuse-live`, `check-acp-session-reuse` |
|
|
176
|
+
| Cross-process continuity / cache before-after | `check-acp-session-store` (signature, decideBootstrap, persist/parse) |
|
|
177
|
+
| Lifecycle policy — a turn-scoped `cwd:` fallback is never a persisted resume/load path; process-scoped records are hashed-`sessionKey` records | `check-acp-session-store` (`resolveLifecyclePolicy` turn-scoped→always-new, `decideBootstrap`, sha256 `SessionRecord` build/parse/roundtrip) — the former inline `acp-bridge.ts` repro is retired with the fat-bridge |
|
|
178
|
+
| Tool-call / event mapping | `check-acp-event-mapper`, `smoke-acp-provider-live` |
|
|
179
|
+
| Operator mcpServers / skills reach the live session | `smoke-acp-mcp-live`, `smoke-acp-skill-live`, `check-acp-config` |
|
|
180
|
+
| Overlay isolation + memory containment | `check-acp-overlay`, `smoke-acp-memory-containment-live`, `check-acp-tool-surface` |
|
|
181
|
+
|
|
182
|
+
### 2.1 MCP callable-identifier shape (verified property, gate-external)
|
|
183
|
+
|
|
184
|
+
The literal callable identifier differs per backend — probe by asking the agent to print it **verbatim** (do not ask "hyphen or underscore" — ambiguous between outer separator and inner server name):
|
|
185
|
+
|
|
186
|
+
| Backend | Literal identifier | Outer sep | Inner server name |
|
|
187
|
+
|---|---|---|---|
|
|
188
|
+
| Claude | `mcp__entwurf-bridge__entwurf_v2` | `__` | `entwurf-bridge` (hyphen) |
|
|
189
|
+
| Codex | `mcp__entwurf_bridge__.entwurf_v2` | `__` | `entwurf_bridge` (underscore) + **literal dot** |
|
|
190
|
+
| Gemini *(probe)* | `mcp_entwurf-bridge_entwurf_v2` | `_` (single) | `entwurf-bridge`, no dot |
|
|
191
|
+
|
|
192
|
+
A Claude session reporting the underscore form, or any cross-shape leak, is a backend-identification leak. Shipped 0.12 baseline is Claude; the Codex/Gemini rows are reference for the probe lanes.
|
|
193
|
+
|
|
194
|
+
### 2.2 MCP injection visibility — equal across resume/load/new
|
|
195
|
+
|
|
196
|
+
The sole MCP responsibility of `entwurf` is to inject `entwurfProvider.mcpServers` equally into `newSession` / `resumeSession` / `loadSession`. Ask "list the visible MCP server names": the registered `entwurf-bridge` appears, unregistered MCPs do not (no automatic `~/.mcp.json` loading); the list is identical every turn; changing `entwurfProvider.mcpServers` changes `bridgeConfigSignature` and forces a new session. `check-acp-config` + `smoke-acp-mcp-live` pin this; the manual check is an honesty corroboration.
|
|
197
|
+
|
|
198
|
+
### 2.3 Process / cache hygiene — the orphan bound (§gate-external judgement)
|
|
199
|
+
|
|
200
|
+
Apply per backend under test:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
AFTER_<BACKEND> ≤ BEFORE_<BACKEND> + (distinct alive
|
|
204
|
+
(sessionKey, backend, modelId, bridgeConfigSignature) tuples this run holds open)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
An **upper bound**, not an equation: child reuse (one `entwurf` + N resumes share one child → delta 0 is expected) and idle reaping push `AFTER` below it; a config-signature or `(provider, model)` switch pushes it up by 1. `AFTER > BEFORE + alive_tuples` is the actionable signal — an unexpected child appeared. Walk the parent chain (`pgrep -af 'claude-agent-acp|codex-acp'` → `ps -o ppid=`); any ACP child whose parent `pi` has exited is an **orphan** — flag and preserve as evidence.
|
|
208
|
+
|
|
209
|
+
### 2.4 pi session record as a shared memory axis
|
|
210
|
+
|
|
211
|
+
The key invariant: **pi session files stay the shared record source even under ACP**. After a reuse pair finishes, locate the child pi session JSONL and confirm turns accumulated:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
ls ~/.pi/agent/sessions/--*--/*_<SESSION_ID>.jsonl # path pattern, not a naive grep (which also hits the parent)
|
|
215
|
+
jq -r '.message.role // .type' "$F" | sort | uniq -c # role lives at .message.role
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Pass: user/assistant turns accumulate normally; the transcript is not broken/empty because ACP was used. We preserve "Claude via ACP, memory via the pi axis (JSONL → Denote/andenken)" — the AI does not run its own memory layer.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 3. Pass criteria — the 0.12 release floor
|
|
223
|
+
|
|
224
|
+
The minimum passing bar:
|
|
225
|
+
|
|
226
|
+
1. **Deterministic floor green:** `pnpm check` passes (lint + typecheck + the `check-*` gate set + `check-pack`).
|
|
227
|
+
2. **Live floor MUST green:** `LIVE=1 ./run.sh release-gate <dir>` reports `MUST PASS=N FAIL=0 SKIP=0`; a BEHAVIOR FAIL is advisory, not blocking.
|
|
228
|
+
3. **Honest self-recognition:** the bridged model identifies the harness as `entwurf`, names its backend, lists `entwurf-bridge` as the single MCP server with its four v2 tools, and presents a **backend-native** (not normalized) tool surface.
|
|
229
|
+
4. **Carrier separation honored:** engraving vs pi-context-augment kept distinct (§1A.0); no bridge-identity narrative attributed to the engraving carrier.
|
|
230
|
+
5. **Boundary preservation across backends/machines:** for every shipped or explicitly probed backend, regardless of install path or host, no cross-backend tool-surface contamination and no confabulation about pi internals.
|
|
231
|
+
6. **Hygiene:** no orphan ACP children; no unexpected persisted session garbage (a turn-scoped `cwd:` fallback is never a persisted reuse).
|
|
232
|
+
|
|
233
|
+
Passing establishes a **release verification floor**, not an 8-hour/day operational guarantee. The floor says: gates hold, the agent honestly recognizes its environment, no tool surface is normalized away, no identity leaks, no orphans. It does **not** say a real-day workload (50–100+ turns, tool bursts, partial MCP failures, auth/version drift) survives — that needs L3–L5 evidence (appendix).
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Appendix — troubleshooting & history
|
|
238
|
+
|
|
239
|
+
### Troubleshooting hooks
|
|
240
|
+
|
|
241
|
+
- **`ENTWURF_CHILD_STDERR_LOG`** mirrors child stderr to a file for bootstrap-path visibility — but it must be present at **bridge-process spawn time**; `export` from a shell already bound to a running bridge does not propagate. Restart the parent session with it exported, then `grep -E '\[entwurf:(bootstrap|model-switch|cancel|shutdown)\]' "$ENTWURF_CHILD_STDERR_LOG"`.
|
|
242
|
+
- **Retired dedicated smokes, live code invariants** (manual/troubleshooting only — *not* part of the release floor):
|
|
243
|
+
- *Model-switch lock* — entwurf sessions are locked to their starting model. Gate: `check-model-lock` (in `pnpm check`). The dedicated live `smoke-model-switch` was retired in v2; the invariant lives in `pi-extensions/model-lock.ts` (extension guard) + `session-store.ts` `SessionModelLockedError` (the `decideBootstrap` fail-loud model lock).
|
|
244
|
+
- *Cancel / abort cleanup* — `onAbort` → `cancelActivePrompt()` (session stays reusable); the stream catch closes the bridge only on `stopReason === "error"`. Dedicated `smoke-cancel` retired; invariant in code.
|
|
245
|
+
- *Transcript-poison invalidation (#12)* — **historical (0.11):** a poisoned backend transcript (empty text block ± `cache_control`) returned the same Anthropic 400 forever, handled by a dedicated classifier + `verify-transcript-poison` smoke. Both were retired in the 0.12 cutover; there is **no dedicated classifier or gate on the current surface** — recorded only so the failure mode is not forgotten.
|
|
246
|
+
|
|
247
|
+
### Evidence preservation when a problem occurs
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
pgrep -af 'claude-agent-acp|codex-acp' || true
|
|
251
|
+
find "$CACHE_DIR" -maxdepth 1 -type f | sort
|
|
252
|
+
ls ~/.pi/agent/sessions/--*--/*_${SESSION_ID}.jsonl 2>/dev/null
|
|
253
|
+
[ -n "$ENTWURF_CHILD_STDERR_LOG" ] && grep -E '\[entwurf:(bootstrap|model-switch|cancel|shutdown)\]' "$ENTWURF_CHILD_STDERR_LOG"
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Also preserve: the exact calls used, full stdout/stderr, the child pi session file path, cache-directory changes, and the expected-vs-actual difference.
|
|
257
|
+
|
|
258
|
+
### History (pointer)
|
|
259
|
+
|
|
260
|
+
The full R2R run history (2026-04-27 → 2026-05-29, pi-shell-acp era), the per-claim evidence ledger (load-bearing claims with level-reached / blind spot / next test, maintained through 0.5.x–0.8.x), and the experimental L3–L5 tracks (4-cell verifier×subject matrix with on-disk corroboration; long-haul soak; direct-native parity panel) live in **CHANGELOG.md and git history**. Evidence reached **L2** (cross-vendor + reverse-direction MCP calls); L3 is partially exercised by the process/session-file checks above; the honest gap is **L3 → L5**. The most recent recorded floor baseline is in [BASELINE.md](./BASELINE.md)'s HISTORY section.
|
package/demo/README.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# entwurf recorded demos
|
|
2
|
+
|
|
3
|
+
> **Archived pre-0.12 evidence.** These scripts still describe the retired v1 `entwurf` / `entwurf_resume` / `entwurf_send` demo flow. They are kept for historical comparison and will be replaced by a v2-native retake in a post-0.12 follow-up; do not treat them as the current 0.12 runnable recipe.
|
|
4
|
+
|
|
5
|
+
Two recorded GIF scripts live here. Both use `asciinema` for capture and
|
|
6
|
+
`agg` for cast → GIF conversion. Both share the same gitignore policy
|
|
7
|
+
(`*.cast` global, `demo/*.gif`, `demo/*.log` — only the `.sh` and this
|
|
8
|
+
README are tracked).
|
|
9
|
+
|
|
10
|
+
## `demo-baseline.sh` — single-pane baseline + entwurf surface
|
|
11
|
+
|
|
12
|
+
Historical pre-0.12 demo, still linked from the top-level `README.md` as archived evidence. `package.json#pi.image` now points at the `entwurf` release hero instead. Two scenes driven into one pi pane:
|
|
13
|
+
|
|
14
|
+
1. **Baseline self-awareness** — the `Q-B0` + `Q-B0-CARRIER` interview,
|
|
15
|
+
English answer enforced. The pane exposes how the running model
|
|
16
|
+
names its harness, distinguishes native tools from MCP / custom
|
|
17
|
+
tools, names the carrier surface for each cited piece of
|
|
18
|
+
information, and admits unknowns instead of fabricating.
|
|
19
|
+
2. **Entwurf surface** — the same pane spawns a sibling via the
|
|
20
|
+
`entwurf` tool (`mode=sync`, cross-model — driver `claude-sonnet-4-6`,
|
|
21
|
+
sibling `gpt-5.4`), prints the Session ID, and quotes the sibling's
|
|
22
|
+
one-line reply verbatim.
|
|
23
|
+
|
|
24
|
+
Run from the repo root (or `demo/`):
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
bash demo/demo-baseline.sh
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Output lands directly in the publish surface — re-running the script
|
|
31
|
+
overwrites the previous take so the gallery preview always matches the
|
|
32
|
+
current branch:
|
|
33
|
+
|
|
34
|
+
- `docs/assets/entwurf-demo.cast` — raw asciinema recording (gitignored)
|
|
35
|
+
- `docs/assets/entwurf-demo.gif` — tracked, referenced by the top-level `README.md` as archived pre-0.12 evidence
|
|
36
|
+
- `demo/baseline-debug.log` — `ENTWURF_DEBUG=1` stderr (gitignored, stays next to the script)
|
|
37
|
+
|
|
38
|
+
## `demo.sh` — two-pane entwurf flow (regression guard)
|
|
39
|
+
|
|
40
|
+
Three-scene entwurf flow used for regression evidence, not for the
|
|
41
|
+
public README. Two pi sessions run side-by-side in one tmux window;
|
|
42
|
+
a background driver types the scene prompts into the sender pane.
|
|
43
|
+
|
|
44
|
+
1. **Spawn** a sonnet sibling (memory write — "tempered indigo").
|
|
45
|
+
2. **Resume** that same sibling (memory recall — identity preservation,
|
|
46
|
+
the #9 regression guard).
|
|
47
|
+
3. **Cross-session greeting** via `entwurf_send` (sent box ↔ received box).
|
|
48
|
+
|
|
49
|
+
Run:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
bash demo/demo.sh
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Output mirrors the baseline demo's layout — recording artifacts land in
|
|
56
|
+
`docs/assets/` so the publish surface and the demo script share one
|
|
57
|
+
naming convention:
|
|
58
|
+
|
|
59
|
+
- `docs/assets/entwurf-entwurf.cast` — raw asciinema recording (gitignored via global `*.cast`)
|
|
60
|
+
- `docs/assets/entwurf-entwurf.gif` — tracked, referenced by the top-level `README.md` Entwurf section
|
|
61
|
+
- `demo/peer-debug.log` — `ENTWURF_DEBUG=1` stderr from the top pane (gitignored, stays next to the script)
|
|
62
|
+
- `demo/sender-debug.log` — same from the bottom pane
|
|
63
|
+
|
|
64
|
+
Watch debug live (separate terminal, before `bash demo.sh`):
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
tail -F demo/sender-debug.log demo/peer-debug.log
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Quick post-run greps:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
grep 'entwurf:debug' demo/sender-debug.log
|
|
74
|
+
grep -E '(entwurf|model-switch)' demo/sender-debug.log
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Tunables (env vars)
|
|
78
|
+
|
|
79
|
+
### `demo.sh` (entwurf two-pane)
|
|
80
|
+
|
|
81
|
+
| Var | Default | Meaning |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `PEER_MODEL` | `entwurf/gpt-5.4` (≡ `piat`) | top pane backend (receives greeting) |
|
|
84
|
+
| `SENDER_MODEL` | `entwurf/claude-sonnet-4-6` (≡ `pias`) | bottom pane backend (drives scenes) |
|
|
85
|
+
| `SCENE_DELAY` | `25` | seconds to wait for each scene's agent work |
|
|
86
|
+
| `WARMUP` | `3` | seconds to wait for both pi banners |
|
|
87
|
+
| `FINAL_PAUSE` | `5` | extra wait after scene 3 (peer reply lag) |
|
|
88
|
+
| `GIF_SPEED` | `2.8` | agg playback multiplier (cast time → GIF time) |
|
|
89
|
+
| `SESSION` | `entwurf-demo` | tmux session name |
|
|
90
|
+
| `OUTDIR` | `demo/` | debug log directory (cast + gif live in `docs/assets/`) |
|
|
91
|
+
|
|
92
|
+
### `demo-baseline.sh` (single-pane baseline + entwurf)
|
|
93
|
+
|
|
94
|
+
| Var | Default | Meaning |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| `DRIVER_MODEL` | `entwurf/claude-sonnet-4-6` (≡ `pias`) | the driven pane — answers Q-B0 and spawns the sibling |
|
|
97
|
+
| `SIBLING_MODEL` | `entwurf/gpt-5.4` (≡ `piat`) | cross-backend sibling spawned in scene 2 |
|
|
98
|
+
| `SIBLING_CWD` | repo root | cwd passed to the entwurf sibling (drives `<project-context>` injection) |
|
|
99
|
+
| `SCENE1_DELAY` | `60` | seconds for the long English baseline answer |
|
|
100
|
+
| `SCENE2_DELAY` | `30` | seconds for the sync entwurf round-trip |
|
|
101
|
+
| `WARMUP` | `3` | seconds to wait for the pi banner |
|
|
102
|
+
| `FINAL_PAUSE` | `4` | extra wait after scene 2 |
|
|
103
|
+
| `GIF_SPEED` | `2.0` | agg playback multiplier (slower than `demo.sh` — the answer rewards reading) |
|
|
104
|
+
| `GIF_COMPRESS` | `1` | run gifsicle after agg (`0` to skip) |
|
|
105
|
+
| `GIF_LOSSY` | `200` | gifsicle `--lossy` strength (drop to `80` if a future scenario shows artifacts) |
|
|
106
|
+
| `GIF_COLORS` | `64` | gifsicle `--colors` palette size |
|
|
107
|
+
| `SESSION` | `entwurf-baseline-demo` | tmux session name |
|
|
108
|
+
| `OUTDIR` | `demo/` | debug log directory (cast + gif live in `docs/assets/`) |
|
|
109
|
+
|
|
110
|
+
### Model ↔ alias map
|
|
111
|
+
|
|
112
|
+
The demo launch lines correspond to your shell aliases:
|
|
113
|
+
|
|
114
|
+
| Alias | Model id | Use as |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `piao` | `entwurf/claude-opus-4-8` | `SENDER_MODEL` (precision scenes) |
|
|
117
|
+
| `pias` | `entwurf/claude-sonnet-4-6` | `SENDER_MODEL` (default) |
|
|
118
|
+
| `piat` | `entwurf/gpt-5.4` | `PEER_MODEL` (default) |
|
|
119
|
+
| `piat5` | `entwurf/gpt-5.5` | either |
|
|
120
|
+
| `piag` | `entwurf/gemini-3.1-pro-preview` | either |
|
|
121
|
+
|
|
122
|
+
Each pane runs with `ENTWURF_DEBUG=1` baked in — same shape as
|
|
123
|
+
the aliases — so every spawn/model-switch/entwurf trace lands in the
|
|
124
|
+
debug log files (see below).
|
|
125
|
+
|
|
126
|
+
Examples:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Swap peer to gemini
|
|
130
|
+
PEER_MODEL=entwurf/gemini-3.1-pro-preview bash demo.sh
|
|
131
|
+
|
|
132
|
+
# Faster pacing for short retake
|
|
133
|
+
SCENE_DELAY=30 FINAL_PAUSE=10 bash demo.sh
|
|
134
|
+
|
|
135
|
+
# All three backends in one demo would need a 3-pane variant — out of scope here.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Prerequisites
|
|
139
|
+
|
|
140
|
+
- `pi` on PATH (current floor 0.80.2)
|
|
141
|
+
- `entwurf` provider configured + auth ready for the selected sender/peer models
|
|
142
|
+
- `asciinema` installed
|
|
143
|
+
- `agg` installed (optional — only for GIF conversion)
|
|
144
|
+
- `gifsicle` installed (optional — `demo-baseline.sh` post-compress step; skip with `GIF_COMPRESS=0`. On NixOS: `nix-shell -p gifsicle` covers both scripts)
|
|
145
|
+
- `tmux` installed
|
|
146
|
+
|
|
147
|
+
If you watch the demo live: open another terminal and run
|
|
148
|
+
`tmux attach -t entwurf-demo -r` (read-only attach) **before** the script
|
|
149
|
+
starts recording. Do not attach writable — keystrokes from your terminal
|
|
150
|
+
would collide with the driver.
|
|
151
|
+
|
|
152
|
+
## Why pre-baked prompts
|
|
153
|
+
|
|
154
|
+
Each scene's prompt asks the inner agent to discover state itself
|
|
155
|
+
(`entwurf_peers`, prior Session ID from this conversation). So the driver
|
|
156
|
+
script types static strings only — no sessionId injection, no
|
|
157
|
+
output parsing. That's what makes it reproducible.
|
|
158
|
+
|
|
159
|
+
## Editing scenes
|
|
160
|
+
|
|
161
|
+
Open `demo.sh`, edit the three `tmux send-keys -t "$SENDER_PANE" -l '...'`
|
|
162
|
+
blocks under the `drive()` function. The `-l` flag tells tmux to send the
|
|
163
|
+
argument literally (no key-name interpretation), so quotes inside the prompt
|
|
164
|
+
are safe as long as you don't use single quotes inside the single-quoted
|
|
165
|
+
argument.
|
|
166
|
+
|
|
167
|
+
## Tracked vs. ignored
|
|
168
|
+
|
|
169
|
+
Tracked (committed):
|
|
170
|
+
|
|
171
|
+
- `demo/demo.sh`
|
|
172
|
+
- `demo/demo-baseline.sh`
|
|
173
|
+
- `demo/README.md`
|
|
174
|
+
- `docs/assets/entwurf-demo.gif` — archived pre-0.12 README demo GIF (no longer `package.json#pi.image`)
|
|
175
|
+
- `docs/assets/entwurf-entwurf.gif` — archived pre-0.12 Entwurf section illustration
|
|
176
|
+
|
|
177
|
+
Ignored (regenerable recording artifacts — both demos):
|
|
178
|
+
|
|
179
|
+
- `*.cast` (global rule — applies under `docs/assets/` too)
|
|
180
|
+
- `demo/*.log`
|
|
181
|
+
|
|
182
|
+
Both demos write their recording artifacts directly into `docs/assets/`
|
|
183
|
+
using the names above. Re-running a demo overwrites the previous take so
|
|
184
|
+
the published preview always matches `main`. The `.cast` source stays
|
|
185
|
+
local (global `*.cast` ignore); only the `.gif` rides the publish surface.
|
|
186
|
+
The `gifsicle` step inside `demo-baseline.sh` makes the take reproducible
|
|
187
|
+
without a manual compression pass — see the Tunables table for tuning the
|
|
188
|
+
lossy/colors flags.
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# demo-baseline.sh — single-pane recorded demo of entwurf.
|
|
3
|
+
#
|
|
4
|
+
# Two scenes, both driven into one pi session:
|
|
5
|
+
# 1. Baseline self-awareness — Q-B0 + Q-B0-CARRIER (English answer enforced).
|
|
6
|
+
# Surfaces system prompt / tool surface / MCP boundary / identity carriers.
|
|
7
|
+
# 2. Entwurf surface — spawn a sibling via the entwurf tool and receive its
|
|
8
|
+
# reply in the same pane (cross-model, mode=sync).
|
|
9
|
+
#
|
|
10
|
+
# Layout (tmux, 220x50):
|
|
11
|
+
# pane 0 (single) — driven pi (claude-sonnet-4-6) — receives both prompts.
|
|
12
|
+
#
|
|
13
|
+
# Recording: asciinema → baseline.cast → agg → baseline.gif
|
|
14
|
+
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
# ---------- config ----------
|
|
18
|
+
SESSION=${SESSION:-entwurf-baseline-demo}
|
|
19
|
+
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
20
|
+
REPO_ROOT=$(cd "$SCRIPT_DIR/.." && pwd)
|
|
21
|
+
# Recording artifacts land in the publish surface (docs/assets/) so the cast
|
|
22
|
+
# + gif are versioned alongside the README/gallery references. The *.cast
|
|
23
|
+
# file remains gitignored (global `*.cast` rule); only the .gif is tracked
|
|
24
|
+
# via the `files` allowlist in package.json. Debug log stays next to the
|
|
25
|
+
# script (gitignored via `demo/*.log`).
|
|
26
|
+
OUTDIR=${OUTDIR:-$SCRIPT_DIR} # debug log dir (local)
|
|
27
|
+
PUBLISH_DIR=${PUBLISH_DIR:-$REPO_ROOT/docs/assets} # cast + gif (publish surface)
|
|
28
|
+
CAST="$PUBLISH_DIR/entwurf-demo.cast"
|
|
29
|
+
GIF="$PUBLISH_DIR/entwurf-demo.gif"
|
|
30
|
+
DRIVER_LOG="$OUTDIR/baseline-debug.log"
|
|
31
|
+
|
|
32
|
+
# Driven pi runs the bridge surface and answers both prompts.
|
|
33
|
+
DRIVER_MODEL=${DRIVER_MODEL:-entwurf/claude-sonnet-4-6} # pias
|
|
34
|
+
# Sibling spawned via entwurf in scene 2 — different backend for contrast.
|
|
35
|
+
SIBLING_MODEL=${SIBLING_MODEL:-entwurf/gpt-5.4} # piat
|
|
36
|
+
SIBLING_CWD=${SIBLING_CWD:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}
|
|
37
|
+
|
|
38
|
+
# Pacing in seconds.
|
|
39
|
+
# Scene 1 produces a long English answer (system-prompt audit); 60 s is the
|
|
40
|
+
# observed upper bound for sonnet-4-6 on this prompt. Scene 2 is shorter
|
|
41
|
+
# (sync entwurf round-trip ≈ 15-25 s).
|
|
42
|
+
WARMUP=${WARMUP:-3}
|
|
43
|
+
SCENE1_DELAY=${SCENE1_DELAY:-60}
|
|
44
|
+
SCENE2_DELAY=${SCENE2_DELAY:-30}
|
|
45
|
+
FINAL_PAUSE=${FINAL_PAUSE:-4}
|
|
46
|
+
|
|
47
|
+
# Slower default than demo.sh (2.8) — Scene 1 produces a long English answer
|
|
48
|
+
# and the audit value comes from being readable, not zippy. Override via env
|
|
49
|
+
# if the recorded GIF still feels too slow for the gallery card.
|
|
50
|
+
GIF_SPEED=${GIF_SPEED:-2.0}
|
|
51
|
+
|
|
52
|
+
# Post-recording gifsicle compression. agg writes ~3 MB for this scenario;
|
|
53
|
+
# gifsicle reliably reproduces ~2 MB with no visible quality loss at lossy=200
|
|
54
|
+
# / colors=64 (text stays legible because monokai uses few distinct hues).
|
|
55
|
+
# Set GIF_COMPRESS=0 to skip; bump GIF_LOSSY down (e.g. 80) for lighter
|
|
56
|
+
# compression if a future scenario shows visible artifacts.
|
|
57
|
+
GIF_COMPRESS=${GIF_COMPRESS:-1}
|
|
58
|
+
GIF_LOSSY=${GIF_LOSSY:-200}
|
|
59
|
+
GIF_COLORS=${GIF_COLORS:-64}
|
|
60
|
+
|
|
61
|
+
EMACS_SOCKET=${PI_EMACS_AGENT_SOCKET:-server}
|
|
62
|
+
|
|
63
|
+
# ---------- prep ----------
|
|
64
|
+
mkdir -p "$OUTDIR" "$PUBLISH_DIR"
|
|
65
|
+
|
|
66
|
+
cleanup() {
|
|
67
|
+
tmux kill-session -t "$SESSION" 2>/dev/null || true
|
|
68
|
+
}
|
|
69
|
+
trap cleanup EXIT
|
|
70
|
+
|
|
71
|
+
tmux kill-session -t "$SESSION" 2>/dev/null || true
|
|
72
|
+
: > "$DRIVER_LOG"
|
|
73
|
+
|
|
74
|
+
# ENTWURF_DEBUG=1 on; stderr appended to debug log so the recorded pane
|
|
75
|
+
# stays clean. --entwurf-control gives the driven session a control socket so
|
|
76
|
+
# entwurf siblings can address it if a follow-up demo needs it.
|
|
77
|
+
COMMON_ENV="ENTWURF_DEBUG=1 PI_EMACS_AGENT_SOCKET=$EMACS_SOCKET"
|
|
78
|
+
COMMON_ARGS="--entwurf-control --emacs-agent-socket $EMACS_SOCKET"
|
|
79
|
+
new_session_id() { bash "$REPO_ROOT/run.sh" new-session-id; }
|
|
80
|
+
|
|
81
|
+
# ---------- start driver (single pane) ----------
|
|
82
|
+
DRIVER_LAUNCH_ID=$(new_session_id)
|
|
83
|
+
tmux new-session -d -s "$SESSION" -n demo -x 220 -y 50 \
|
|
84
|
+
"$COMMON_ENV pi --session-id $DRIVER_LAUNCH_ID --model $DRIVER_MODEL $COMMON_ARGS 2>>$DRIVER_LOG"
|
|
85
|
+
DRIVER_PANE=$(tmux list-panes -s -t "$SESSION" -F '#{pane_id}' | head -1)
|
|
86
|
+
|
|
87
|
+
# Give pi time to print its banner and reach the prompt.
|
|
88
|
+
sleep "$WARMUP"
|
|
89
|
+
|
|
90
|
+
# ---------- driver: types both prompts into the single pane ----------
|
|
91
|
+
drive() {
|
|
92
|
+
# Scene 1 — baseline self-awareness (Q-B0 + Q-B0-CARRIER). Answer in English.
|
|
93
|
+
tmux send-keys -t "$DRIVER_PANE" -l '[Q-B0] What does your system prompt say? Answer without speculation. 1. What harness / tool environment are you in right now? 2. Distinguish native tools from MCP / custom tools. 3. What is the basis for that understanding? 4. Do not pretend to see what you do not see — say "I do not know" when you do not. [Q-B0-CARRIER] For each piece of information cited above, identify the surface: 1. Actual system prompt (or, on Codex, the developer instruction). 2. First-user-message prepend. 3. Tool function schema. 4. Separate system-reminder block. Also: (a) if asked to commit something to memory, how do you handle it; (b) can you check today personal Google Calendar via the provided skills? Please answer in English.'
|
|
94
|
+
tmux send-keys -t "$DRIVER_PANE" Enter
|
|
95
|
+
sleep "$SCENE1_DELAY"
|
|
96
|
+
|
|
97
|
+
# Scene 2 — entwurf surface: spawn a sibling, receive its reply inline.
|
|
98
|
+
tmux send-keys -t "$DRIVER_PANE" -l "Now demonstrate the entwurf surface. Spawn a sibling via the entwurf tool — provider: entwurf, model: gpt-5.4, mode: sync, cwd: $SIBLING_CWD. Task body: \"You are a sibling spawned for a recorded demo. Reply in one English sentence: which backend ACP model are you running on, and what does the entwurf_self envelope say about your identity (sessionId, agentId, cwd)?\". After the entwurf returns, print the Session ID and quote the sibling reply verbatim in one line."
|
|
99
|
+
tmux send-keys -t "$DRIVER_PANE" Enter
|
|
100
|
+
sleep $((SCENE2_DELAY + FINAL_PAUSE))
|
|
101
|
+
|
|
102
|
+
# End: detach asciinema by killing tmux session.
|
|
103
|
+
tmux kill-session -t "$SESSION" 2>/dev/null || true
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
drive &
|
|
107
|
+
DRIVE_PID=$!
|
|
108
|
+
|
|
109
|
+
# ---------- record ----------
|
|
110
|
+
asciinema rec --overwrite --quiet \
|
|
111
|
+
--command "tmux attach -t $SESSION" \
|
|
112
|
+
"$CAST" || true
|
|
113
|
+
|
|
114
|
+
wait "$DRIVE_PID" 2>/dev/null || true
|
|
115
|
+
|
|
116
|
+
# ---------- convert to gif ----------
|
|
117
|
+
if command -v agg >/dev/null 2>&1; then
|
|
118
|
+
echo "Converting cast → gif via agg (speed=${GIF_SPEED})..."
|
|
119
|
+
agg --speed "$GIF_SPEED" --theme monokai "$CAST" "$GIF"
|
|
120
|
+
AGG_SIZE=$(stat -c%s "$GIF" 2>/dev/null || stat -f%z "$GIF" 2>/dev/null || echo "?")
|
|
121
|
+
echo "GIF (uncompressed): $GIF (${AGG_SIZE} bytes)"
|
|
122
|
+
else
|
|
123
|
+
echo "agg not found; keeping cast only: $CAST"
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# ---------- compress gif (gifsicle) ----------
|
|
127
|
+
# Same flags that produced the committed docs/assets/entwurf-demo.gif —
|
|
128
|
+
# rerunning this script reproduces a comparable artifact, not a 3 MB raw take.
|
|
129
|
+
if [ "$GIF_COMPRESS" = "1" ] && [ -f "$GIF" ]; then
|
|
130
|
+
if command -v gifsicle >/dev/null 2>&1; then
|
|
131
|
+
echo "Compressing GIF via gifsicle (-O3 --lossy=${GIF_LOSSY} --colors ${GIF_COLORS})..."
|
|
132
|
+
TMP_GIF="${GIF}.uncompressed"
|
|
133
|
+
mv "$GIF" "$TMP_GIF"
|
|
134
|
+
gifsicle -O3 --lossy="$GIF_LOSSY" --colors "$GIF_COLORS" "$TMP_GIF" -o "$GIF"
|
|
135
|
+
rm -f "$TMP_GIF"
|
|
136
|
+
GIFS_SIZE=$(stat -c%s "$GIF" 2>/dev/null || stat -f%z "$GIF" 2>/dev/null || echo "?")
|
|
137
|
+
echo "GIF (compressed): $GIF (${GIFS_SIZE} bytes)"
|
|
138
|
+
else
|
|
139
|
+
echo "gifsicle not found; GIF left uncompressed (set GIF_COMPRESS=0 to silence)."
|
|
140
|
+
echo " Install: 'nix-shell -p gifsicle' or your distro's package."
|
|
141
|
+
fi
|
|
142
|
+
elif [ "$GIF_COMPRESS" = "0" ]; then
|
|
143
|
+
echo "GIF_COMPRESS=0 — skipping gifsicle pass."
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# ---------- summary ----------
|
|
147
|
+
echo "Cast: $CAST"
|
|
148
|
+
echo "Driver log: $DRIVER_LOG ($(wc -l < "$DRIVER_LOG" 2>/dev/null || echo 0) lines)"
|
|
149
|
+
echo
|
|
150
|
+
echo "Quick debug peek:"
|
|
151
|
+
echo " grep 'entwurf:debug' $DRIVER_LOG | head -20"
|
|
152
|
+
echo " grep -E '(entwurf|model-switch)' $DRIVER_LOG | head -20"
|
|
153
|
+
echo
|
|
154
|
+
echo "Recording artifacts land directly in the publish surface:"
|
|
155
|
+
echo " $CAST"
|
|
156
|
+
echo " $GIF (tracked — referenced by package.json#pi.image + README)"
|