@junghanacs/entwurf 0.34.2 → 0.35.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/CHANGELOG.md +115 -0
- package/README.md +7 -0
- package/VERIFY.md +11 -1
- package/demo/README.md +109 -175
- package/demo/demo-baseline.sh +5 -1
- package/demo/demo.sh +6 -2
- package/demo/herdr-pi-cc-20261011.provenance.json +64 -0
- package/docs/assets/entwurf-demo.gif +0 -0
- package/package.json +4 -2
- package/run.sh +37 -0
- package/scripts/check-gate-qualification.ts +2 -1
- package/scripts/check-release-gate-outcomes.ts +159 -1
- package/scripts/ci-qualify-decide.sh +114 -17
- package/scripts/mutants/demo-reproducibility.json +155 -0
- package/scripts/mutants/release-gate.json +28 -2
- package/scripts/tsconfig.json +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,121 @@ All notable changes to this project will be documented here. Format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.35.0 - 2026-10-12
|
|
8
|
+
|
|
9
|
+
### Collaboration and qualification
|
|
10
|
+
|
|
11
|
+
- **A renewed demo after the 0.12.0 transition.** This is the first newly recorded
|
|
12
|
+
collaboration demo release since the 0.12.0 hard cut from `pi-shell-acp` to `entwurf`.
|
|
13
|
+
The capability is visible again in a real shared workbench, while #137 reduces redundant
|
|
14
|
+
qualification work without introducing a blanket plugin or data-file exemption.
|
|
15
|
+
- **Real Pi ↔ native Claude Code collaboration in Herdr (#138).** The README now shows the
|
|
16
|
+
accepted whole-workbench recording below the hero, linked to the Herdr section. The original
|
|
17
|
+
GIF bytes were published without captions or a retake; recording tooling remains separate.
|
|
18
|
+
- **Restore maintainer demo recipes and source tooling (#138).** The checkout now carries
|
|
19
|
+
the take/renderer/helpers and Node fixtures, including the actual whole-Herdr recipe and
|
|
20
|
+
original publication provenance. A new LIVE take is distinct from the private original;
|
|
21
|
+
missing historical tool versions are not invented. Archived v1 scripts refuse before any
|
|
22
|
+
command. Every LIVE scene refuses a non-approved selector or OpenRouter redirect first, and
|
|
23
|
+
missing LIVE cannot allocate capture resources; mixed subject/terminal tails are
|
|
24
|
+
kept, absent recording cannot certify success, and rerendering preserves the original
|
|
25
|
+
take's agg input. The renderer refuses publication destinations and parent aliases;
|
|
26
|
+
publication still requires separate review and copy. Source tests have their own discovered
|
|
27
|
+
Node floor and type fence, while maintainer TypeScript stays out of the installed package.
|
|
28
|
+
Neither source tooling nor the narrow privacy scan certifies a package consumer, original
|
|
29
|
+
capture replay, or whole-host/public-readability acceptance.
|
|
30
|
+
- **Avoid redundant qualification for untouched TOML find ranges (#137).** Push replay reads
|
|
31
|
+
manifests at the named HEAD and checks every joined find span on both blobs. Only exact-once,
|
|
32
|
+
unmoved, untouched TOML spans may skip. Markdown/JSON data stays file-level, because a
|
|
33
|
+
shorter presence literal or a later duplicate JSON key outside the find can re-satisfy an
|
|
34
|
+
oracle. Code/unknown subjects, signature sources and deciding machinery also remain
|
|
35
|
+
file-level, and uncertainty runs the body. The FULL floor and exact-SHA core
|
|
36
|
+
release qualification obligation are unchanged. The earlier source landing kept 0.34.2;
|
|
37
|
+
this separate preparation moves the core package to 0.35.0.
|
|
38
|
+
|
|
39
|
+
### Release boundary and verification
|
|
40
|
+
|
|
41
|
+
- **Reviewed source, not borrowed release evidence.** The implementation commit `52cdd7f`
|
|
42
|
+
follows the final consistency closure and independent review. Its frozen source candidate
|
|
43
|
+
passed the FULL deterministic floor in 762 seconds with HEAD, index and work surface
|
|
44
|
+
unchanged. Affected PARTIAL groups killed all 24 release-gate and 12 demo claims at their
|
|
45
|
+
owning QK signatures, with four green controls; the other 904 claims were not run locally.
|
|
46
|
+
The set now contains 940 distinct claims. Those local receipts are development evidence,
|
|
47
|
+
not a whole qualification pass. The later test-only checkpoint `41a8d78` closes fixture
|
|
48
|
+
cleanup on green and assertion-red paths, including the fake recorder's owned teardown.
|
|
49
|
+
Its affected demo PARTIAL killed all 12 claims at their QKs with two green controls,
|
|
50
|
+
followed by frozen FULL 766s/0 on identical source/index/HEAD. All five measured fixture
|
|
51
|
+
prefixes had zero new residue; historical and original/native evidence was preserved.
|
|
52
|
+
- **Whole qualification BODY deferred by explicit operator instruction for this cut.**
|
|
53
|
+
The operator requested main publication without repeating the approximately 95-minute
|
|
54
|
+
qualification body. The ordinary push uses a one-commit `[skip ci]` marker to prevent its
|
|
55
|
+
automatic start; the existing `workflow_dispatch` with `qualify=false` can run the four
|
|
56
|
+
ordinary CI jobs without the body. This changes no product gate or workflow wiring.
|
|
57
|
+
A floor-only run is not exact-SHA whole qualification acceptance, and no skipped BODY
|
|
58
|
+
is reported as PASS. The unchanged release oracle would refuse it; make's preserved
|
|
59
|
+
artifact/tag/GitHub Release sequence remains pending, rather than bypassing that oracle.
|
|
60
|
+
- **Supply the real GIF decoder to the offline CI floor, not to the product.** The first
|
|
61
|
+
floor-only main run `38170795980` passed the three install/artifact jobs but stopped
|
|
62
|
+
`check:full` on the new demo fixtures because Ubuntu lacked `ffprobe` (`ENOENT`).
|
|
63
|
+
The check job now installs Ubuntu's `ffmpeg` package before the FULL floor and records
|
|
64
|
+
the decoder version. The fixtures still fake the renderer/caption tools and judge real
|
|
65
|
+
GIF bytes through `ffprobe`; no decoding assertion or missing-tool failure is skipped.
|
|
66
|
+
This is job-only scaffolding, not operator/global or npm setup. The CI recovery result
|
|
67
|
+
belongs in #137/#138's live checkpoint; the original failed run remains historical.
|
|
68
|
+
- **Native Codex LIVE is explicitly deferred for this cut, to the next release.** The operator
|
|
69
|
+
requested its exclusion from this verification. No native Codex sibling/app-server or turn
|
|
70
|
+
is started, and its product MUST wiring remains intact. This is an unmeasured per-cut
|
|
71
|
+
exception, not PASS or a standing waiver. Other required axes remain required; record
|
|
72
|
+
their actual outcomes and any named Codex SKIP separately, never round that SKIP green.
|
|
73
|
+
The earlier frozen versioned candidate's LIVE aggregate ran in
|
|
74
|
+
`/tmp/entwurf-release-gate-0.35.0.wypGz0/release-gate.log`: MUST PASS=23 FAIL=0 SKIP=1
|
|
75
|
+
(only native Codex), BEHAVIOR PASS=1 FAIL=0 SKIP=0, standard `--cut` exit 1 / BLOCKED.
|
|
76
|
+
Its runtime observation predates the test-only fixture checkpoint and is not borrowed
|
|
77
|
+
as that changed candidate's full release acceptance.
|
|
78
|
+
- **Unpublished candidate verification carrier.** The npm-source lock must agree with the
|
|
79
|
+
checkout's core version, so the 0.35.0 preparation temporarily uses the existing closed
|
|
80
|
+
`herdr-checkout` carrier without inventing an npm integrity. The published 0.34.2 pin and
|
|
81
|
+
Herdr manifest version remain historical/separate; this is not a Herdr 0.35.0 snapshot.
|
|
82
|
+
A host that changes acquisition source must explicitly deactivate/activate, never inherit
|
|
83
|
+
an activation. Operator installations are not rewired by this preparation. After the
|
|
84
|
+
operator publishes core 0.35.0, the later Herdr snapshot must re-pin the measured registry
|
|
85
|
+
bytes and perform literal #137 next-plugin acceptance; neither is claimed here.
|
|
86
|
+
- **Publication boundary.** The latest instruction narrows this lane to the 0.35.0 main
|
|
87
|
+
preparation and ordinary push, then a completion handoff. npm publication belongs to
|
|
88
|
+
the operator; after it, the Herdr plugin's separate 0.35.0 snapshot and measured npm
|
|
89
|
+
re-pin can follow. No npm publication, Herdr version bump or registry pin is executed
|
|
90
|
+
here. No accepted make artifact, core tag or GitHub Release is claimed prematurely.
|
|
91
|
+
|
|
92
|
+
## v2026.10.11-herdr.0.34.2 — Herdr Entwurf plugin 0.34.2
|
|
93
|
+
|
|
94
|
+
A Herdr plugin snapshot, not a core release: no package version, npm artifact or core tag moves.
|
|
95
|
+
|
|
96
|
+
### Herdr plugin
|
|
97
|
+
|
|
98
|
+
- **Runtime re-pinned to the published 0.34.2 (#136).** `plugins/herdr/runtime-lock.json` returns
|
|
99
|
+
from the `herdr-checkout` verification carrier the 0.34.2 preparation rode to the npm production
|
|
100
|
+
source: `@junghanacs/entwurf@0.34.2` with the registry's measured sha512
|
|
101
|
+
(`sha512-RbEkv3Ha…s/5ksg==`). The manifest version moves 0.34.1 → 0.34.2; `min_herdr_version`
|
|
102
|
+
stays 0.9.0. The checkout window is closed. A plugin host now receives the #136 fix: its
|
|
103
|
+
runtime's `doctor-meta-bridge` derives plugin-runtime mode from the activation ledger and
|
|
104
|
+
certifies the activation's absolute wiring.
|
|
105
|
+
- **Upgrading.** A host on the npm 0.34.1 snapshot stays on the npm source, so its next
|
|
106
|
+
`herdr plugin install` is a same-source rebind under the plugin README's conditions. A host that
|
|
107
|
+
installed from `main` while the lock named `herdr-checkout` needs `herdr-plugin-deactivate` by
|
|
108
|
+
its absolute runtime path, then `herdr plugin install` again.
|
|
109
|
+
|
|
110
|
+
### Verification
|
|
111
|
+
|
|
112
|
+
- **Registry, measured before the pin.** `npm view` reports version 0.34.2 with `latest` →
|
|
113
|
+
0.34.2 and `repair` → 0.12.8-repair.1. The downloaded tarball is 13595042 bytes with sha256
|
|
114
|
+
`e75efb0c…c009`, equal to the artifact accepted as 0.34.2. Its sha512, computed independently
|
|
115
|
+
from those bytes, equals `dist.integrity`. A sandboxed `pi install
|
|
116
|
+
npm:@junghanacs/entwurf@0.34.2` resolved the bridge to the registry install and listed the
|
|
117
|
+
`entwurf` models.
|
|
118
|
+
- The focused Herdr gates, `pnpm check`, the public `main` install journey and the exact-SHA CI run
|
|
119
|
+
on the pushed commit will be recorded in the GitHub release and #136, not claimed here. No gate, mutant or matrix changed, so no
|
|
120
|
+
qualification PARTIAL is owed.
|
|
121
|
+
|
|
7
122
|
## 0.34.2 - 2026-10-11
|
|
8
123
|
|
|
9
124
|
### Release coordination
|
package/README.md
CHANGED
|
@@ -6,6 +6,13 @@ transcript, authentication, tools, or runtime.
|
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
9
|
+
**Pi ↔ native Claude Code inside the [Herdr workbench](#herdr-workbench).**
|
|
10
|
+
A recorded source-checkout demo: callback → task → native Bash → reply.
|
|
11
|
+
[Source recipe and original provenance](demo/README.md#whole-herdr-pi--native-claude-code-138)
|
|
12
|
+
(the recipe creates a new take; the original private capture is not shipped).
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
9
16
|
[](https://www.npmjs.com/package/@junghanacs/entwurf) · maintained by [junghanacs.com](https://junghanacs.com/)
|
|
10
17
|
|
|
11
18
|
A sibling is a visible session with its own runtime boundary, not a disposable
|
package/VERIFY.md
CHANGED
|
@@ -58,6 +58,15 @@ install and pack gates that consume a tarball; gates that spawn a subprocess or
|
|
|
58
58
|
gates that read product source as text; and the mutant EXECUTION COORDINATES described below. A
|
|
59
59
|
new hand-built gate needs a reason one of those five applies.
|
|
60
60
|
|
|
61
|
+
The maintainer demo lane (#138) is source-only Node strip-types/CLI and subprocess
|
|
62
|
+
fixtures, not an installed adapter contract. Its `demo/**/*.test.ts` uses `node:test`,
|
|
63
|
+
so `check-demo-reproducibility` discovers and runs it separately in the deterministic
|
|
64
|
+
floor, with sandboxed HOME/XDG and fake version-only Pi metadata. Do not add Node tests
|
|
65
|
+
to the Vitest include and call them reached. Take/renderer/helper TS stays out of the
|
|
66
|
+
package; the paired scripts type fence checks it. Fake-tool tests, private original
|
|
67
|
+
capture, a new opt-in LIVE take, published GIF approval and exact release/package
|
|
68
|
+
acceptance remain distinct axes; see [the source recipe](./demo/README.md).
|
|
69
|
+
|
|
61
70
|
**Four rules bind a migrated gate that carries mutants**, and each of them was measured rather
|
|
62
71
|
than assumed (#119 V3 slice 2):
|
|
63
72
|
|
|
@@ -87,6 +96,7 @@ that moved out of `scripts/` and into a file beside its subject would otherwise
|
|
|
87
96
|
|
|
88
97
|
- **Deterministic floor — two tiers (#70):** `pnpm check` is the everyday CORE — toolchain (lint + typecheck), the vitest lanes, and the pure-unit / behavioral-contract / source-topology gates plus the cheap static coherence checks. It prints its own total wall time; acceptance is ≤60s on the reference host `oracle` (an operator measurement, never a hard wall-clock gate on arbitrary hosts). `pnpm run check:full` is the FULL deterministic floor — the core plus the hermetic-integration and package/install tiers — and is what the frozen-candidate protocol, push CI, release-gate, and `prepublishOnly` run. Exact membership is the named `check:*` group scripts in `package.json` (the executable SSOT — this document records meaning and principles, not the command list); a gate changes tier by semantic-class decision, never by getting faster or slower. One core member assumes a build output: the beside test `pi-extensions/entwurf-control.test.ts` (reached through `check-tests-beside-behavior`) registers the COMPILED bridge and refuses by name when it is absent. `prepare` normally builds it at install; after an `--ignore-scripts` install or a bridge source change, run `pnpm run build-bridge` (in the sandbox candidate when verifying one) before the core. The FULL tier carries the qualification HEAD (`check-gate-manifests`, through `check:hermetic`); the everyday core does not, and neither tier carries the separately scheduled mutant-executing body (`check-gate-qualification`).
|
|
89
98
|
- **Discriminating power of that floor:** `./run.sh check-gate-qualification` (scheduled, not ambient: the whole body runs only as the bare call — in the CI `check` job on a branch push that touched the qualification surface, and — for a cut — at the prepared SHA, where the exact-SHA release oracle requires that CI step once and the prepared state awaits it, never presumed PASS; a cut therefore batches its commits into that one prepared push (#132 took the cut's body off the local `release-gate`). Development runs no whole body (#133): a lane that changes a gate/mutant/matrix runs its affected exact-argv groups once, after review, as PARTIAL receipts — `./run.sh check-gate-qualification --group '<argv JSON>' --receipt <absolute path outside the repo>`, whose arguments reach the runner's parser unchanged and are refused there by name, before any body or snapshot, when malformed, missing or repeated. A receipt is a measurement of one group, never a qualification pass. Neither form is inside the default check chains; a semver TAG push triggers no CI at all, and the exact-SHA evidence a release quotes is whichever run at that commit CARRIES the body — the branch run when the push touched the qualification surface, else a dispatch run; a push that touched none of the qualification surface skips the body, and `workflow_dispatch -f qualify=true` plus a weekly `schedule` run it unconditionally — the exact-SHA release oracle refuses a SHA whose body step did not conclude success) re-plants committed defect mutants (`scripts/mutants/*.json`, one per closed defect class) in an isolated snapshot repo and requires each to turn its gate red **bounded and at its claimed `[QK:<claim>]` signature** — a wrong-reason red fails, a baseline-red control voids the whole group, and the runner is negative-controlled on every run (zero-match/multi-match/survived/wrong-reason/hang/control-red/impurity). This measures whether the deterministic gates still *block* what they claim to block; it is **not a new evidence level** (L0–L5 are untouched) and never substitutes for LIVE evidence. Per-cut records cite claim IDs + killed mutant IDs — "N checks passed" alone is not evidence. `check-agy-permission-matrix` complements it with the enumerated permission contract space (literal cells + stated exclusion rules, oracle independent of the SUT). The gate's HEAD is separable and IS in the floor: `check-gate-manifests` runs the runner self-test, validates the committed manifest set against the origin index, and asserts the declared lane inventory, while executing zero COMMITTED mutants (the self-test runs only its synthetic fixture mutants, in tmp fixture repos) and never snapshotting the repo — three of the five reds qualification has ever produced in CI died in that head, in under five seconds.
|
|
99
|
+
- **Push matching is conservative and hunk-aware (#137).** Git ranges read mutant manifests from the named HEAD commit, not a later working tree. Signature sources and the existing deciding machinery always match at file level, including paths that are also subjects. Only TOML subjects (`.toml`) may skip, and only when every mutant's joined `find` span occurs exactly once on both blobs, stays on the same lines, and intersects no zero-context diff hunk. Markdown, JSON, code and unknown subject types remain file-level. An outside-find early return/import/caller change can weaken a code mutant without editing its literal find. A presence/`includes` oracle whose required literal is shorter than the find can be re-satisfied by an out-of-span restatement; a scratch-repo probe measured exactly that false SKIP for `ADMISSION-LEGACY-DOCUMENTED` in `DELIVERY.md`. A later duplicate JSON key wins under `JSON.parse`, which every current JSON data oracle uses. TOML refuses a redefined key, and the current TOML oracles are exact-count/absence checks; a future TOML subject with a presence oracle reopens this boundary. `QUALIFY-FILTER-TOML-ONLY-REFINEMENT` pins Markdown/JSON at file level. Moved, absent, ambiguous, binary or unreadable spans/diffs/manifests run the body with a named reason; renames are compared as delete/add. `--files-from` has no hunk evidence and retains path identity. There is no Herdr filename or release-shape exemption. Span matching is not proof of unchanged kill-power. The rule narrows per-push qualification to those declared TOML spans; forced/scheduled and exact-SHA release qualification remain the backstop. This narrows redundant data-only pushes, never the FULL floor or exact-SHA release body's obligation; a body-less plugin SHA cannot supply the core SHA's evidence.
|
|
90
100
|
- **The snapshot is source-only (#125).** It replicates the git work surface and never copies an ignored artifact from the checkout. A gate that consumes an ignored build output — the compiled `entwurf-bridge` a pi citizen registers — declares it on each of its mutants (`"build": {"argv": [...], "output": "<dir>"}`, one declaration per gate group). For that group only, the runner builds the output from the snapshot's own bytes before the control, rebuilds it after every mutation and from the restored bytes before the post-control (which must reproduce the baseline digest), never counts a build red as a kill, voids a run whose gate writes into the output, and removes the output when the group ends. The runner self-test owns this as `[QK:QUALIFY-BUILD-*]`.
|
|
91
101
|
- **Live floor:** `LIVE=1 ./run.sh release-gate <scratch-project-dir> --cut` — `pnpm run check:full` + the v2-native live gates + the ACP plugin acceptance floor. It reports a **two-tier summary**:
|
|
92
102
|
- **MUST tier** (release-blocking — owns the exit code; "green" applies only here): `pnpm run check:full`, `smoke-entwurf-v2-matrix-live`, `check-bridge`, `doctor-pi-provider` (#81 — `check-bridge` proves the launcher this checkout SHIPS; this proves the invocation the operator's pi provider actually EXECS, by booting it and requiring the entwurf verb set back, because `command -v` answers yes for a command that exits 127; wired as a step on 2026-08-19 after a relocated pnpm cmd-shim cost a cut sixteen LIVE steps before the same fact surfaced at `smoke-acp-bundled-mcp-live`), the resident-garden-guard zero-token half (record birth / record-keyed socket / attach-on-reopen), the `smoke-acp-*-live` ACP plugin smokes (socket-citizen / raw-turn / overlay / provider / session-reuse / carrier-augment / memory-containment / rgg / mcp / skill / bundled-mcp / v2-send), the axis wired in on 2026-07-31 that the aggregate had simply never listed (`smoke-claude-native-resume-live`), `smoke-entwurf-chain-live` — the cross-harness delivery chain (native Claude Code → pi GPT → pi ACP Sonnet → mailbox terminus) proving sender identity and replyability at every hop plus a real read receipt at the end — the integrated `smoke-mux-lifecycle-live` (its own note below), and the two OMP steps 0.16.0 wired: `smoke-omp-receive-live` (the addressed roundtrip into a live omp citizen; it reads the capability registry and decides its own outcome rather than passing by default) and `smoke-omp-fresh-live` (the clause 7 receipt the release stop now requires). (`smoke-session-id-name` is gone — #50 C3: its `--session-id`/`--name` substrate has no entwurf consumer anymore.)
|
|
@@ -96,7 +106,7 @@ that moved out of `scripts/` and into a file beside its subject would otherwise
|
|
|
96
106
|
|
|
97
107
|
> **The herdr rail is an on-demand axis until it has run.** `smoke-herdr-fresh-call-live` opens a real caller inside a real herdr pane, has it invoke the PUBLIC `entwurf_fresh_call`, and reads the child's nonce callback — the one axis no deterministic gate reaches, since the rail is selected from the caller's own process environment. **The release aggregate does not yet require the herdr rail**: herdr is optional (a cut on a host without it must not block), and first evidence precedes promotion — a rail whose first acceptance run is days old has not earned a place in the gate that blocks every cut. Run it directly with `LIVE=1 ./run.sh smoke-herdr-fresh-call-live` whenever a cut changes herdr rail code, and promote it to a MUST only after the axis has a run history to point at. Without `LIVE=1`, or without herdr/pi/claude on PATH, it reports protocol SKIP — never a pass.
|
|
98
108
|
|
|
99
|
-
> **The plugin's FIRST USER PATH is its own on-demand axis, and an npm acquisition receipt holds only for the ref it ran on (#118 홉 1).** Every other herdr gate proves the plugin against a source this repository controls: `check-herdr-plugin-build` drives a stub, and `smoke-herdr-plugin-build-live` redirects the product remote to a local bare clone with git `insteadOf` and asserts `identity.kind === "herdr-checkout"`. npm has been the production authority class since `dd84ac0`; the 0.30.0 follow-up re-pinned `@junghanacs/entwurf@0.30.0` with its published sha512 after the candidate windows rode `herdr-checkout` (`8b92e09`), and the 0.30.1 preparation rode that closed verification carrier again without inventing a registry integrity. The plugin snapshot `v2026.10.9-herdr.0.34.0` pinned the published `@junghanacs/entwurf@0.34.0` with its measured sha512 (#132); 0.31–0.33 were never pinned. The 0.34.1 preparation rode the closed `herdr-checkout` verification carrier again without inventing a registry integrity, and the snapshot `v2026.10.9-herdr.0.34.1` re-pins the published `@junghanacs/entwurf@0.34.1` with its measured sha512 (#135). The source re-proof has separate dated npm rows: 2026-09-23 public `main=113ca53`, plugin 0.5.0, runtime 0.25.0 (CHANGELOG 0.25.1), and the 0.30.0 re-pin accepted at public `506c46f` in the [#126 thread](https://github.com/junghan0611/entwurf/issues/126). Neither certifies the 0.34.0 registry acquisition. That pin's real-npm swap / torn-swap recovery was measured locally on 2026-10-09 by driving the registry-shipped `scripts/herdr-runtime.mjs` (byte-equal to this checkout's) with its own npm acquisition: a 0.33.0 → 0.34.0 swap, and the same upgrade torn between its two renames then resumed, where the last-good 0.33.0 tree was restored before 0.34.0 was acquired again. Both ended `runtime-ready` at observed digest `sha256-e9d995ff…`, the accepted 0.34.0 artifact. That local receipt is recorded in the [#132 thread](https://github.com/junghan0611/entwurf/issues/132); it covers runtime recovery, not this smoke's cells. This smoke's public-ref acceptance of the 0.34.0 pin was measured locally at `--ref main`: PASS at resolved `b5d15d8` and again at the docs follow-up `8ed4d1a`, each acquiring `kind=npm @junghanacs/entwurf@0.34.0` — a main-ref receipt, not a tag-ref, native or full-Herdr claim. The 0.34.1 re-pin's npm-source rows — swap / torn-swap recovery, this smoke at a public ref, and the package consumer — are its own, recorded with that pin and never inherited from 0.34.0; checkout candidate evidence does not transfer. `LIVE=1 ./run.sh smoke-herdr-raw-install-live [--ref <REF>]` fills that row in a clean `node:24` container with no socket, config, cache or repo mounted, no `insteadOf`, the public remote spelled as a user would type it, and pi / herdr / Claude Code installed in the IMAGE BUILD as scaffolding (Hard Rule 17 — the product face begins at `herdr integration install pi`). herdr itself comes from `scripts/install-herdr-ci.sh` against `scripts/fixtures/herdr-supply.json`, so no version or digest lives here. `--ref` defaults to `main` rather than a pinned SHA because receipt (a) is defined as what a user gets today; the resolved commit is printed, so the receipt stays exact. It takes a REMOTE REF and not an arbitrary commit — measured on herdr 0.9.1, `--ref <sha>` fails as `couldn't find remote ref`, because the checkout fetches by name — so a candidate is addressed by its branch and pinned by the resolved commit the gate prints. **Its first question is a measurement, not an assumption:** herdr registers a plugin through a running server and falls back to `persist_plugin_offline` only on a connection error (`src/cli/plugin.rs:914-981,1016-1021` @ `c77af189`, 0.9.0 source), and a container has no server. The 2026-09-23 PASS installed with no server on the 0.9.1 binary `113ca53`'s `herdr-supply.json` pins, so that install path worked on 0.9.1 — inferred from the PASS, not a direct observation of the fallback branch; a later "no" on another herdr is #118 investigation output rather than a completion. `--yes` is always passed so a non-interactive exit 2 (`:189`) can never be misread as a missing server. **At a ref whose lock names `herdr-checkout` the acquisition axis reports a NAMED SKIP rather than a red, and the rest of the journey still runs.** That lock is the candidate carrier a cut legitimately sits on — 0.23.0 was tagged that way and `dd84ac0` pinned npm afterwards — so a red there would report a broken install when what is true is that the ref does not lock npm. What is asserted at BOTH lock kinds is that the runtime came from the source the ref locks, and the package name is read from the checkout manifest rather than the lock, because a `herdr-checkout` lock carries no `name` (`herdr-runtime.mjs:317-328`) and joining `undefined` throws instead of failing an assertion. **Cells [6]–[9] carry it past the install into the USE path (#118 H1-4/H1-5).** An install is not a use, so the same container then runs what those bytes became: the compiled bridge entry, the three `REQUIRED_BINS` as executables, and a real `entwurf check-bridge` printing its exact eight-verb set — the installed-runtime row below, measured rather than inferred from the bootstrap's refusal to install without them. Then the pi that this plugin WIRED is started with no `-e` and no `--no-extensions`, because the subject is the wiring and not this checkout: one `get_state` in `--mode rpc` costs zero tokens and needs no provider argument (a bogus `--provider` exits 1 before session_start; omitting the pair lets pi resolve the default the extension itself registers), and while that session is alive the cell reads its V3 record, its gardenId-keyed control socket, and the installed `entwurf peer-facts` reporting it `alive`. The plugin's own status fan is then driven with NEITHER side stubbed, in both states a user can be in: with no herdr server it must name `herdr-agent-list-failed` and go red rather than draw an empty table, and under a headless `herdr server` — scaffolding for that second read only, stopped again before the teardown — it exits 0 and COUNTS the citizen as `unobserved` instead of dropping it. Last, the shipped `entwurf herdr-plugin-deactivate` runs from the installed bin, deletes the runtime it is executing from, and the plugin reinstalls onto the host it fully left — the deactivation row, on the npm source. **What these cells still do not close:** swap / torn-swap recovery on the npm source, the package-consumer proof, and the fan drawing a citizen as a ROW — that needs `placement.kind === "herdr-pane"`, so the pi session must live in a herdr pane a session reference joins, and a headless container has no panes. **This smoke carries no test beside behavior and no mutant**, and that is a property of its class rather than an omission: it is a real-live container journey whose oracle is the container's own end state, so there is no pure seam to assert against and nothing a source mutation could kill deterministically. Like the other two herdr LIVE lanes it is **on-demand and not an aggregate MUST** — herdr is optional, a cut on a host without it must not block, and first evidence precedes promotion. Without `LIVE=1`, or without a usable Docker daemon, it reports a named SKIP; `ENTWURF_REQUIRE_DOCKER=1` turns the Docker absence red. Neither skip is a pass.
|
|
109
|
+
> **The plugin's FIRST USER PATH is its own on-demand axis, and an npm acquisition receipt holds only for the ref it ran on (#118 홉 1).** Every other herdr gate proves the plugin against a source this repository controls: `check-herdr-plugin-build` drives a stub, and `smoke-herdr-plugin-build-live` redirects the product remote to a local bare clone with git `insteadOf` and asserts `identity.kind === "herdr-checkout"`. npm has been the production authority class since `dd84ac0`; the 0.30.0 follow-up re-pinned `@junghanacs/entwurf@0.30.0` with its published sha512 after the candidate windows rode `herdr-checkout` (`8b92e09`), and the 0.30.1 preparation rode that closed verification carrier again without inventing a registry integrity. The plugin snapshot `v2026.10.9-herdr.0.34.0` pinned the published `@junghanacs/entwurf@0.34.0` with its measured sha512 (#132); 0.31–0.33 were never pinned. The 0.34.1 preparation rode the closed `herdr-checkout` verification carrier again without inventing a registry integrity, and the snapshot `v2026.10.9-herdr.0.34.1` re-pins the published `@junghanacs/entwurf@0.34.1` with its measured sha512 (#135). The 0.34.2 preparation rode the same carrier, and the snapshot `v2026.10.11-herdr.0.34.2` re-pins the published `@junghanacs/entwurf@0.34.2` with its measured sha512 (#136). The source re-proof has separate dated npm rows: 2026-09-23 public `main=113ca53`, plugin 0.5.0, runtime 0.25.0 (CHANGELOG 0.25.1), and the 0.30.0 re-pin accepted at public `506c46f` in the [#126 thread](https://github.com/junghan0611/entwurf/issues/126). Neither certifies the 0.34.0 registry acquisition. That pin's real-npm swap / torn-swap recovery was measured locally on 2026-10-09 by driving the registry-shipped `scripts/herdr-runtime.mjs` (byte-equal to this checkout's) with its own npm acquisition: a 0.33.0 → 0.34.0 swap, and the same upgrade torn between its two renames then resumed, where the last-good 0.33.0 tree was restored before 0.34.0 was acquired again. Both ended `runtime-ready` at observed digest `sha256-e9d995ff…`, the accepted 0.34.0 artifact. That local receipt is recorded in the [#132 thread](https://github.com/junghan0611/entwurf/issues/132); it covers runtime recovery, not this smoke's cells. This smoke's public-ref acceptance of the 0.34.0 pin was measured locally at `--ref main`: PASS at resolved `b5d15d8` and again at the docs follow-up `8ed4d1a`, each acquiring `kind=npm @junghanacs/entwurf@0.34.0` — a main-ref receipt, not a tag-ref, native or full-Herdr claim. The 0.34.1 re-pin's npm-source rows — swap / torn-swap recovery, this smoke at a public ref, and the package consumer — are its own, recorded with that pin and never inherited from 0.34.0; checkout candidate evidence does not transfer. `LIVE=1 ./run.sh smoke-herdr-raw-install-live [--ref <REF>]` fills that row in a clean `node:24` container with no socket, config, cache or repo mounted, no `insteadOf`, the public remote spelled as a user would type it, and pi / herdr / Claude Code installed in the IMAGE BUILD as scaffolding (Hard Rule 17 — the product face begins at `herdr integration install pi`). herdr itself comes from `scripts/install-herdr-ci.sh` against `scripts/fixtures/herdr-supply.json`, so no version or digest lives here. `--ref` defaults to `main` rather than a pinned SHA because receipt (a) is defined as what a user gets today; the resolved commit is printed, so the receipt stays exact. It takes a REMOTE REF and not an arbitrary commit — measured on herdr 0.9.1, `--ref <sha>` fails as `couldn't find remote ref`, because the checkout fetches by name — so a candidate is addressed by its branch and pinned by the resolved commit the gate prints. **Its first question is a measurement, not an assumption:** herdr registers a plugin through a running server and falls back to `persist_plugin_offline` only on a connection error (`src/cli/plugin.rs:914-981,1016-1021` @ `c77af189`, 0.9.0 source), and a container has no server. The 2026-09-23 PASS installed with no server on the 0.9.1 binary `113ca53`'s `herdr-supply.json` pins, so that install path worked on 0.9.1 — inferred from the PASS, not a direct observation of the fallback branch; a later "no" on another herdr is #118 investigation output rather than a completion. `--yes` is always passed so a non-interactive exit 2 (`:189`) can never be misread as a missing server. **At a ref whose lock names `herdr-checkout` the acquisition axis reports a NAMED SKIP rather than a red, and the rest of the journey still runs.** That lock is the candidate carrier a cut legitimately sits on — 0.23.0 was tagged that way and `dd84ac0` pinned npm afterwards — so a red there would report a broken install when what is true is that the ref does not lock npm. What is asserted at BOTH lock kinds is that the runtime came from the source the ref locks, and the package name is read from the checkout manifest rather than the lock, because a `herdr-checkout` lock carries no `name` (`herdr-runtime.mjs:317-328`) and joining `undefined` throws instead of failing an assertion. **Cells [6]–[9] carry it past the install into the USE path (#118 H1-4/H1-5).** An install is not a use, so the same container then runs what those bytes became: the compiled bridge entry, the three `REQUIRED_BINS` as executables, and a real `entwurf check-bridge` printing its exact eight-verb set — the installed-runtime row below, measured rather than inferred from the bootstrap's refusal to install without them. Then the pi that this plugin WIRED is started with no `-e` and no `--no-extensions`, because the subject is the wiring and not this checkout: one `get_state` in `--mode rpc` costs zero tokens and needs no provider argument (a bogus `--provider` exits 1 before session_start; omitting the pair lets pi resolve the default the extension itself registers), and while that session is alive the cell reads its V3 record, its gardenId-keyed control socket, and the installed `entwurf peer-facts` reporting it `alive`. The plugin's own status fan is then driven with NEITHER side stubbed, in both states a user can be in: with no herdr server it must name `herdr-agent-list-failed` and go red rather than draw an empty table, and under a headless `herdr server` — scaffolding for that second read only, stopped again before the teardown — it exits 0 and COUNTS the citizen as `unobserved` instead of dropping it. Last, the shipped `entwurf herdr-plugin-deactivate` runs from the installed bin, deletes the runtime it is executing from, and the plugin reinstalls onto the host it fully left — the deactivation row, on the npm source. **What these cells still do not close:** swap / torn-swap recovery on the npm source, the package-consumer proof, and the fan drawing a citizen as a ROW — that needs `placement.kind === "herdr-pane"`, so the pi session must live in a herdr pane a session reference joins, and a headless container has no panes. **This smoke carries no test beside behavior and no mutant**, and that is a property of its class rather than an omission: it is a real-live container journey whose oracle is the container's own end state, so there is no pure seam to assert against and nothing a source mutation could kill deterministically. Like the other two herdr LIVE lanes it is **on-demand and not an aggregate MUST** — herdr is optional, a cut on a host without it must not block, and first evidence precedes promotion. Without `LIVE=1`, or without a usable Docker daemon, it reports a named SKIP; `ENTWURF_REQUIRE_DOCKER=1` turns the Docker absence red. Neither skip is a pass.
|
|
100
110
|
|
|
101
111
|
> **The Herdr plugin's install-time build has two axes, and one of them needs the network (#116 M3-b3).** `check-herdr-plugin-build` is deterministic and rides `check:hermetic`: the listing reaches the runner through its own spawn seam (there is no fake `herdr` binary in this repo), and the one cell that drives the REAL binary reports a named SKIP on a host without it — `ENTWURF_REQUIRE_HERDR=1` makes that absence red. What it cannot have is the real acquisition: `npm pack git+https://github.com/junghan0611/entwurf.git#<full sha>` builds the bridge through `prepare`, which installs devDependencies from the registry. So `LIVE=1 ./run.sh smoke-herdr-plugin-build-live` owns that axis, and its cells are **two kinds of evidence, labelled as such**: three are the real Herdr journey — a real `herdr plugin install` driving the real `[[build]]`, with the UNCHANGED product remote redirected to a local bare clone by git `insteadOf` (the one substitution, which is what makes an unpushed candidate testable) — covering remote-commit available, the `{pi}` → `{pi, claude-code}` reinstall with OpenCode as a zero-write negative control and exactly ONE counted vendor MCP owner entry, and the post-build Herdr-commit gap (where the ledger has already rebound to the gap commit, so the honest assertion is that transition and not unchanged bytes). The fourth cell — remote-commit **unavailable** — calls the shipped runtime leaf directly with the fixed product argv and is therefore **acquisition-leaf evidence, not a journey**; routing it through Herdr would add a second explanation for one red. Its oracle is the honest one too: active runtime, ledger and harness bytes preserved, while the journal is left as the certified `installing` retry authority the transaction deliberately writes before acquiring, and a normal install afterwards is green. Its Claude cell is where the vendor question the deterministic gates refuse to claim gets answered — whether Claude Code accepts an ABSOLUTE executable as an MCP command — and it reports a named skip on a host without `claude`, never a pass. Like the herdr fresh-call rail, this smoke is **on-demand and not an aggregate MUST**. The release aggregate does not require the plugin build smoke: herdr is optional, a cut on a host without it must not block, and first evidence precedes promotion.
|
|
102
112
|
|
package/demo/README.md
CHANGED
|
@@ -1,193 +1,127 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
# Recorded demos — source checkout recipes
|
|
2
|
+
|
|
3
|
+
## Whole Herdr: Pi ↔ native Claude Code (#138)
|
|
4
|
+
|
|
5
|
+
This is the scene shown by the [README GIF](../README.md). The recording is the **whole
|
|
6
|
+
Herdr client**, with sidebar and tabs, without captions. It observes a real Pi citizen
|
|
7
|
+
opening native Claude Code, receiving its callback, sending one task, and receiving the
|
|
8
|
+
sibling's native Bash result. Camera focus is a view, never an address or delivery receipt.
|
|
9
|
+
|
|
10
|
+
### Original publication versus a new take
|
|
11
|
+
|
|
12
|
+
[Original provenance](./herdr-pi-cc-20261011.provenance.json) records the approved GIF hash,
|
|
13
|
+
original cast hash, measured runtime/models, audited source hashes and render arguments.
|
|
14
|
+
The original raw cast, transcripts, native records and full manifests remain private.
|
|
15
|
+
**A fresh checkout cannot replay that original capture.** The command below creates a
|
|
16
|
+
**new LIVE take of the same scene**, not byte-identical GIF reproduction or renewed
|
|
17
|
+
acceptance of the original. Model text, timing, ids and terminal banners vary. The original
|
|
18
|
+
agg/ffprobe versions were not recorded; current tool versions cannot retroactively fill them.
|
|
19
|
+
|
|
20
|
+
### Prerequisites — no automatic install or repair
|
|
21
|
+
|
|
22
|
+
Run from an installed development **source checkout**, not an npm consumer. The `.ts`
|
|
23
|
+
takes/helpers/tests are maintainer tooling and are deliberately excluded from the tarball.
|
|
24
|
+
|
|
25
|
+
- Node at the `package.json#engines.node` floor; the checkout's pinned dependencies and
|
|
26
|
+
current compiled bridge. After a source/bootstrap change, build with `pnpm run build-bridge`.
|
|
27
|
+
- Pi at the checkout's supported floor (**current floor 1.1.0**); `entwurf` on PATH must be
|
|
28
|
+
the intended source stable-bin. Source evidence is not registry-package acceptance.
|
|
29
|
+
- `herdr` on PATH at exactly `scripts/fixtures/herdr-supply.json#version`; `asciinema` v3.
|
|
30
|
+
- Herdr's existing Pi integration at
|
|
31
|
+
`${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}/extensions/herdr-agent-state.ts`.
|
|
32
|
+
- The operator's existing Claude launcher/auth and vendor data at
|
|
33
|
+
`${XDG_DATA_HOME:-$HOME/.local/share}/claude`. Missing or drifted ownership is a refusal,
|
|
34
|
+
not permission to install, copy credentials or fix global hooks/settings.
|
|
35
|
+
- For offline rendering only: `agg` and `ffprobe` on PATH. Rendering is optional and
|
|
36
|
+
requires the original private `take.cast` **and its same-run manifest**.
|
|
37
|
+
|
|
38
|
+
Selectors for this scene are fixed: Pi `openai-codex/gpt-6.1-sol`, thinking `low`, native
|
|
39
|
+
Claude Code alias `sonnet`. Overrides may only restate these. An OpenRouter base-URL
|
|
40
|
+
redirect is refused before inference; no fallback model or automatic retry is used.
|
|
41
|
+
A requested alias and the native model id observed in its transcript are recorded separately.
|
|
42
|
+
|
|
43
|
+
### Offline verification first
|
|
27
44
|
|
|
28
45
|
```bash
|
|
29
|
-
|
|
46
|
+
./run.sh check-demo-reproducibility
|
|
47
|
+
pnpm exec tsc --noEmit -p scripts/tsconfig.json
|
|
30
48
|
```
|
|
31
49
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
50
|
+
The named source-only floor verb discovers `demo/**/*.test.ts` and runs Node's own test
|
|
51
|
+
runner, including fake-tool/child-process fixtures. It is reached by `pnpm check` and
|
|
52
|
+
`pnpm run check:full`; these are not Vitest tests and are not reached by the adapter beside
|
|
53
|
+
Vitest globs. HOME, writable XDG roots and identity carriers are sandboxed by the verb.
|
|
54
|
+
`agg` and `ffmpeg` are faked, but the renderer/caption fixtures decode real GIF bytes, so
|
|
55
|
+
this floor needs a real `ffprobe` on PATH; without it they fail (`ffprobe ENOENT`) rather
|
|
56
|
+
than skip. CI installs Ubuntu's `ffmpeg` package (which carries `ffprobe`) in the check job.
|
|
57
|
+
The receiving type fence is `scripts/tsconfig.json`, paired with the root `demo` exclusion.
|
|
39
58
|
|
|
40
|
-
|
|
59
|
+
### Explicit new LIVE take
|
|
41
60
|
|
|
42
|
-
|
|
43
|
-
public README. Two pi sessions run side-by-side in one tmux window;
|
|
44
|
-
a background driver types the scene prompts into the sender pane.
|
|
45
|
-
|
|
46
|
-
1. **Spawn** a sonnet sibling (memory write — "tempered indigo").
|
|
47
|
-
2. **Resume** that same sibling (memory recall — identity preservation,
|
|
48
|
-
the #9 regression guard).
|
|
49
|
-
3. **Cross-session greeting** via `entwurf_send`. *(Historical: `entwurf_send` was retired in the
|
|
50
|
-
0.12 cutover, and the "sent box" half of that pairing was never actually reachable — the
|
|
51
|
-
sender-side renderer had zero producers and was removed in #120 P3. What the recording shows on
|
|
52
|
-
the receive side is real; the send side is a box the operator could not have seen.)*
|
|
53
|
-
|
|
54
|
-
Run:
|
|
61
|
+
Only run after deciding to spend real subscription turns:
|
|
55
62
|
|
|
56
63
|
```bash
|
|
57
|
-
|
|
64
|
+
LIVE=1 node demo/take-herdr-pi-cc.ts
|
|
58
65
|
```
|
|
59
66
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
With approved selectors/policy and without `LIVE=1`, it exits 97 **before tool preflight
|
|
68
|
+
or resource creation**. Invalid selectors or an OpenRouter redirect can refuse earlier
|
|
69
|
+
with exit 2, still without tools or writes. Once authorized, it creates a private Herdr
|
|
70
|
+
server/fence, starts the scene, and stops only resources whose
|
|
71
|
+
ownership it can prove. Failure ends observation; it cannot undo a citizen's completed work.
|
|
72
|
+
No automatic retry, rerender or promotion follows a failure. Failed evidence is retained.
|
|
63
73
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
The fence isolates Herdr XDG state and Entwurf record/mailbox roots, **not the whole host**:
|
|
75
|
+
HOME/auth/vendor stores remain real; the existing Claude data directory is linked into the
|
|
76
|
+
private fence. Pi's control socket and the addressed v2 lock use real `~/.pi/` directories.
|
|
77
|
+
The native transcripts, records and fence are kept, not erased by teardown. Do not run this
|
|
78
|
+
against an operator server or broaden cleanup to unrelated sessions.
|
|
68
79
|
|
|
69
|
-
|
|
80
|
+
The default output is `.tmp-verify/138-demo-gifs/takes/<take-id>/` (ignored); an explicit
|
|
81
|
+
`ENTWURF_DEMO_OUT` changes its parent. `manifest.json` contains assertions, camera views,
|
|
82
|
+
raw receipts, measured models and the cast digest. The stage describes source **tooling**;
|
|
83
|
+
`entwurfOnPath` is observed, not checked against this checkout's stable-bin. Confirm that
|
|
84
|
+
binding separately before calling a take source-runtime evidence. Git HEAD and dirty state
|
|
85
|
+
are observed; a dirty HEAD is **not** an immutable source fingerprint.
|
|
86
|
+
Keep the exact source and manifest with any subsequent take you intend to audit.
|
|
70
87
|
|
|
71
|
-
|
|
72
|
-
tail -F demo/sender-debug.log demo/peer-debug.log
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Quick post-run greps:
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
grep 'entwurf:debug' demo/sender-debug.log
|
|
79
|
-
grep -E '(entwurf|model-switch)' demo/sender-debug.log
|
|
80
|
-
```
|
|
88
|
+
### Offline rendering and publication boundary
|
|
81
89
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
### `demo.sh` (entwurf two-pane)
|
|
85
|
-
|
|
86
|
-
| Var | Default | Meaning |
|
|
87
|
-
|---|---|---|
|
|
88
|
-
| `PEER_MODEL` | `entwurf/gpt-5.4` (≡ `piat`) | top pane backend (receives greeting) |
|
|
89
|
-
| `SENDER_MODEL` | `entwurf/claude-sonnet-5` (≡ `pias`) | bottom pane backend (drives scenes) |
|
|
90
|
-
| `SCENE_DELAY` | `25` | seconds to wait for each scene's agent work |
|
|
91
|
-
| `WARMUP` | `3` | seconds to wait for both pi banners |
|
|
92
|
-
| `FINAL_PAUSE` | `5` | extra wait after scene 3 (peer reply lag) |
|
|
93
|
-
| `GIF_SPEED` | `2.8` | agg playback multiplier (cast time → GIF time) |
|
|
94
|
-
| `SESSION` | `entwurf-demo` | tmux session name |
|
|
95
|
-
| `OUTDIR` | `demo/` | debug log directory (cast + gif live in `docs/assets/`) |
|
|
96
|
-
|
|
97
|
-
### `demo-baseline.sh` (single-pane baseline + entwurf)
|
|
98
|
-
|
|
99
|
-
| Var | Default | Meaning |
|
|
100
|
-
|---|---|---|
|
|
101
|
-
| `DRIVER_MODEL` | `entwurf/claude-sonnet-5` (≡ `pias`) | the driven pane — answers Q-B0 and spawns the sibling |
|
|
102
|
-
| `SIBLING_MODEL` | `entwurf/gpt-5.4` (≡ `piat`) | cross-backend sibling spawned in scene 2 |
|
|
103
|
-
| `SIBLING_CWD` | repo root | cwd passed to the entwurf sibling (drives `<project-context>` injection) |
|
|
104
|
-
| `SCENE1_DELAY` | `60` | seconds for the long English baseline answer |
|
|
105
|
-
| `SCENE2_DELAY` | `30` | seconds for the sync entwurf round-trip |
|
|
106
|
-
| `WARMUP` | `3` | seconds to wait for the pi banner |
|
|
107
|
-
| `FINAL_PAUSE` | `4` | extra wait after scene 2 |
|
|
108
|
-
| `GIF_SPEED` | `2.0` | agg playback multiplier (slower than `demo.sh` — the answer rewards reading) |
|
|
109
|
-
| `GIF_COMPRESS` | `1` | run gifsicle after agg (`0` to skip) |
|
|
110
|
-
| `GIF_LOSSY` | `200` | gifsicle `--lossy` strength (drop to `80` if a future scenario shows artifacts) |
|
|
111
|
-
| `GIF_COLORS` | `64` | gifsicle `--colors` palette size |
|
|
112
|
-
| `SESSION` | `entwurf-baseline-demo` | tmux session name |
|
|
113
|
-
| `OUTDIR` | `demo/` | debug log directory (cast + gif live in `docs/assets/`) |
|
|
114
|
-
|
|
115
|
-
### Model ↔ alias map
|
|
116
|
-
|
|
117
|
-
The demo launch lines correspond to your shell aliases:
|
|
118
|
-
|
|
119
|
-
| Alias | Model id | Use as |
|
|
120
|
-
|---|---|---|
|
|
121
|
-
| `piao` | `entwurf/claude-opus-5` | `SENDER_MODEL` (precision scenes) |
|
|
122
|
-
| `pias` | `entwurf/claude-sonnet-5` | `SENDER_MODEL` (default) |
|
|
123
|
-
| `piat` | `entwurf/gpt-5.4` | `PEER_MODEL` (default) |
|
|
124
|
-
| `piat5` | `entwurf/gpt-5.5` | either |
|
|
125
|
-
| `piag` | `entwurf/gemini-3.1-pro-preview` | either |
|
|
126
|
-
|
|
127
|
-
Each pane runs with `ENTWURF_DEBUG=1` baked in — same shape as
|
|
128
|
-
the aliases — so every spawn/model-switch/entwurf trace lands in the
|
|
129
|
-
debug log files (see below).
|
|
130
|
-
|
|
131
|
-
Examples:
|
|
90
|
+
Given an existing same-run private take, no model turn is needed:
|
|
132
91
|
|
|
133
92
|
```bash
|
|
134
|
-
|
|
135
|
-
PEER_MODEL=entwurf/gemini-3.1-pro-preview bash demo.sh
|
|
136
|
-
|
|
137
|
-
# Faster pacing for short retake
|
|
138
|
-
SCENE_DELAY=30 FINAL_PAUSE=10 bash demo.sh
|
|
139
|
-
|
|
140
|
-
# All three backends in one demo would need a 3-pane variant — out of scope here.
|
|
93
|
+
node demo/render-take.ts <private-take-dir> <private-output.gif>
|
|
141
94
|
```
|
|
142
95
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
- `demo/demo.sh`
|
|
177
|
-
- `demo/demo-baseline.sh`
|
|
178
|
-
- `demo/README.md`
|
|
179
|
-
- `docs/assets/entwurf-demo.gif` — archived pre-0.12 README demo GIF (no longer `package.json#pi.image`)
|
|
180
|
-
- `docs/assets/entwurf-entwurf.gif` — archived pre-0.12 Entwurf section illustration
|
|
181
|
-
|
|
182
|
-
Ignored (regenerable recording artifacts — both demos):
|
|
183
|
-
|
|
184
|
-
- `*.cast` (global rule — applies under `docs/assets/` too)
|
|
185
|
-
- `demo/*.log`
|
|
186
|
-
|
|
187
|
-
Both demos write their recording artifacts directly into `docs/assets/`
|
|
188
|
-
using the names above. Re-running a demo overwrites the previous take so
|
|
189
|
-
the published preview always matches `main`. The `.cast` source stays
|
|
190
|
-
local (global `*.cast` ignore); only the `.gif` rides the publish surface.
|
|
191
|
-
The `gifsicle` step inside `demo-baseline.sh` makes the take reproducible
|
|
192
|
-
without a manual compression pass — see the Tunables table for tuning the
|
|
193
|
-
lossy/colors flags.
|
|
96
|
+
The renderer verifies cast digest, trims only recorder-only teardown, and promotes the
|
|
97
|
+
private GIF only after agg exits successfully and ffprobe decodes it. Each render keeps a
|
|
98
|
+
uniquely named `.render.cast` beside its output (also on failure), with name/digest in a
|
|
99
|
+
successful sidecar; the original take's `take.render.cast` is never overwritten. Non-live-pass takes
|
|
100
|
+
can render only to a private FAILED name. A mixed subject/teardown event is retained whole.
|
|
101
|
+
The renderer refuses repository `docs/assets/` destinations, including parent-directory
|
|
102
|
+
aliases: **publication is a separate reviewed copy**, never a rendering side effect.
|
|
103
|
+
|
|
104
|
+
Its email/company-path scan is deliberately narrow, **not a privacy/public-readability
|
|
105
|
+
certificate**: personal paths, hostnames, footers and native progress language can remain.
|
|
106
|
+
The operator approved the original rough pixels with their disclosed limitations. A new
|
|
107
|
+
render requires its own review; it must not overwrite the approved original implicitly.
|
|
108
|
+
The GIF and sidecar rename separately; a crash between them leaves a mismatched pair, not
|
|
109
|
+
atomic two-file publication. Optional `caption-take.ts` produces a separate derivative;
|
|
110
|
+
it is not this uncaptioned publication recipe.
|
|
111
|
+
|
|
112
|
+
## Other source scenes
|
|
113
|
+
|
|
114
|
+
`take-pi-durable.ts`, `take-pi-acp.ts` and `take-pi-cc.ts` record **different**, private tmux
|
|
115
|
+
scenes. Each requires its own explicit `LIVE=1` and, like the Herdr scene, refuses a
|
|
116
|
+
non-approved selector or an OpenRouter base-URL redirect first (exit 2, no tools or writes).
|
|
117
|
+
They are not the Herdr GIF's recipe.
|
|
118
|
+
Their helper tests remain in the same offline discovery verb. Original FAILED takes and
|
|
119
|
+
offline rejudgements are distinct evidence, never replacement LIVE acceptance.
|
|
120
|
+
|
|
121
|
+
## Archived pre-0.12 scripts
|
|
122
|
+
|
|
123
|
+
`demo-baseline.sh` and `demo.sh` retain their historical bodies for comparison, but now
|
|
124
|
+
**refuse immediately with exit 2**, even with `LIVE=1`. They cannot launch retired v1 flows
|
|
125
|
+
or overwrite today's published assets. Historical commands, selectors and old output paths
|
|
126
|
+
inside those bodies are tombstones, not runnable advice. Scene 3's current deterministic
|
|
127
|
+
delivery proof is `./run.sh check-bridge-delivery`; do not revive the v1 route.
|
package/demo/demo-baseline.sh
CHANGED
|
@@ -25,7 +25,11 @@
|
|
|
25
25
|
|
|
26
26
|
set -euo pipefail
|
|
27
27
|
|
|
28
|
-
#
|
|
28
|
+
# Hard retirement: the preserved v1 body must never launch or overwrite today's approved GIF.
|
|
29
|
+
printf '%s\n' 'entwurf demo: archived v1 baseline refused; see demo/README.md for the source-only Herdr recipe.' >&2
|
|
30
|
+
exit 2
|
|
31
|
+
|
|
32
|
+
# ---------- historical body (unreachable) ----------
|
|
29
33
|
SESSION=${SESSION:-entwurf-baseline-demo}
|
|
30
34
|
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
31
35
|
REPO_ROOT=$(cd "$SCRIPT_DIR/.." && pwd)
|
package/demo/demo.sh
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# retired v1 verbs (`entwurf` / `entwurf_resume` / `entwurf_send`), which the 0.12
|
|
6
6
|
# cutover removed; a run would fail at scene 1. Kept for historical comparison only.
|
|
7
7
|
# See demo/README.md. Scene 3's delivery proof was recovered as a deterministic gate
|
|
8
|
-
# (scripts/check-bridge-delivery.ts);
|
|
8
|
+
# (scripts/check-bridge-delivery.ts); current v2-native source recipes live in demo/README.md.
|
|
9
9
|
#
|
|
10
10
|
#
|
|
11
11
|
# MODEL NOTE (2026-08-20). The model ids below are the ARCHIVED values these
|
|
@@ -28,7 +28,11 @@
|
|
|
28
28
|
|
|
29
29
|
set -euo pipefail
|
|
30
30
|
|
|
31
|
-
#
|
|
31
|
+
# Hard retirement: preserve historical source, not a second runnable v1 route.
|
|
32
|
+
printf '%s\n' 'entwurf demo: archived v1 peer scene refused; see demo/README.md for current source recipes.' >&2
|
|
33
|
+
exit 2
|
|
34
|
+
|
|
35
|
+
# ---------- historical body (unreachable) ----------
|
|
32
36
|
SESSION=${SESSION:-entwurf-demo}
|
|
33
37
|
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
34
38
|
REPO_ROOT=$(cd "$SCRIPT_DIR/.." && pwd)
|