@junghanacs/entwurf 0.24.0 → 0.25.1

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +564 -0
  2. package/CONTRIBUTING.md +1 -1
  3. package/DELIVERY.md +24 -1
  4. package/README.md +2 -2
  5. package/VERIFY.md +20 -2
  6. package/demo/README.md +5 -2
  7. package/docs/acp-backend-rail.md +49 -2
  8. package/docs/setup-clean-host.md +4 -4
  9. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +5 -4
  10. package/mcp/entwurf-bridge/dist/pi-extensions/lib/control-send-receipt.js +101 -0
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +6 -2
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +17 -1
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-runner.js +4 -0
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-send.js +53 -6
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +38 -3
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +13 -3
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-placement.js +11 -0
  18. package/mcp/entwurf-bridge/dist/protocol.js +0 -7
  19. package/mcp/entwurf-bridge/dist/scripts/doctor-pi-provider.js +40 -3
  20. package/mcp/entwurf-bridge/dist/scripts/herdr-rails.mjs +72 -0
  21. package/mcp/entwurf-bridge/src/index.ts +5 -4
  22. package/package.json +10 -9
  23. package/pi-extensions/entwurf-control.ts +27 -154
  24. package/pi-extensions/lib/compaction-send-guard.ts +5 -3
  25. package/pi-extensions/lib/control-send-receipt.ts +108 -0
  26. package/pi-extensions/lib/entwurf-v2-contract-schema.ts +1 -1
  27. package/pi-extensions/lib/entwurf-v2-contract.ts +6 -2
  28. package/pi-extensions/lib/entwurf-v2-production.ts +19 -1
  29. package/pi-extensions/lib/entwurf-v2-runner.ts +23 -1
  30. package/pi-extensions/lib/entwurf-v2-send.ts +82 -6
  31. package/pi-extensions/lib/entwurf-v2-surface.ts +42 -3
  32. package/pi-extensions/lib/herdr-fresh-call.ts +13 -3
  33. package/pi-extensions/lib/herdr-placement.ts +11 -0
  34. package/protocol.js +0 -8
  35. package/run.sh +202 -33
  36. package/scripts/check-entwurf-v2-surface.ts +289 -10
  37. package/scripts/check-gate-qualification.ts +2354 -11
  38. package/scripts/check-herdr-fresh-call.ts +10 -2
  39. package/scripts/check-herdr-placement.ts +51 -0
  40. package/scripts/check-herdr-plugin-build.ts +11 -4
  41. package/scripts/check-herdr-plugin.ts +745 -38
  42. package/scripts/check-mux-launcher-fence.ts +37 -0
  43. package/scripts/check-pi-launch.ts +7 -4
  44. package/scripts/check-release-gate-outcomes.ts +165 -0
  45. package/scripts/doctor-pi-provider.ts +44 -4
  46. package/scripts/herdr-rails.mjs +75 -0
  47. package/scripts/lib/qualification-acceptance.ts +146 -0
  48. package/scripts/lib/qualification-artifact.ts +359 -0
  49. package/scripts/lib/qualification-collection.ts +384 -0
  50. package/scripts/lib/qualification-gh.ts +231 -0
  51. package/scripts/lib/qualification-ledger.ts +669 -0
  52. package/scripts/lib/qualification-oracle-core.ts +279 -0
  53. package/scripts/lib/qualification-receipt.ts +561 -0
  54. package/scripts/lib/qualification-release.ts +271 -0
  55. package/scripts/meta-bridge-state.py +18 -1
  56. package/scripts/mutants/bridge-command-boot.json +38 -0
  57. package/scripts/mutants/control-send-receipt.json +235 -0
  58. package/scripts/mutants/herdr-fresh-call.json +4 -4
  59. package/scripts/mutants/herdr-plugin-build.json +7 -11
  60. package/scripts/mutants/herdr-plugin.json +177 -9
  61. package/scripts/mutants/meta-retire.json +22 -0
  62. package/scripts/mutants/pack-install.json +4 -4
  63. package/scripts/mutants/pi-floor.json +17 -0
  64. package/scripts/mutants/qualification-ledger.json +489 -0
  65. package/scripts/mutants/release-gate.json +48 -0
  66. package/scripts/mutants/retired-sent-surface.json +32 -0
  67. package/scripts/mutants/v2-surface.json +7 -7
  68. package/scripts/qualification-oracle.ts +124 -0
  69. package/scripts/smoke-codex-fresh-live.ts +94 -13
  70. package/scripts/smoke-herdr-fresh-call-live.ts +15 -8
  71. package/scripts/smoke-herdr-raw-install-live.sh +66 -4
  72. package/scripts/smoke-meta-install-state.sh +107 -1
  73. package/scripts/smoke-mux-lifecycle-live.ts +9 -2
  74. package/scripts/smoke-pi-provider-state.sh +106 -0
  75. package/scripts/smoke-setup-verdict.sh +18 -2
@@ -344,10 +344,18 @@ async function main(): Promise<void> {
344
344
  const code = MODULE_SRC.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
345
345
  const specifiers = [...MODULE_SRC.matchAll(/^import\s[^;]*?from\s+"([^"]+)";$/gm)].map((m) => m[1]);
346
346
  ok(
347
- "[QK:HFC-RAIL-IMPORT-FENCE] the herdr rail imports only node builtins, the neutral composition leaf, and the callback-env pair — one mux or entwurf import here would re-couple the two rails and make either one undeletable",
347
+ "[QK:HFC-RAIL-IMPORT-FENCE] the herdr rail imports only node builtins, the neutral composition leaf, the callback-env pair, and the dependency-free rails DECLARATION leaf — one mux or entwurf import here would re-couple the two rails and make either one undeletable",
348
348
  specifiers.length > 0 &&
349
349
  specifiers.every(
350
- (s) => s.startsWith("node:") || s === "./fresh-call-composition.ts" || s === "./callback-env.ts",
350
+ (s) =>
351
+ s.startsWith("node:") ||
352
+ s === "./fresh-call-composition.ts" ||
353
+ s === "./callback-env.ts" ||
354
+ // #116 A7 — the ONE place the backend tuple and the per-backend model syntax
355
+ // example are written, shared with the status pane and the install narration.
356
+ // It imports nothing itself, so admitting it couples this rail to a constant
357
+ // rather than to another rail; the mux/entwurf ban below is untouched.
358
+ s === "../../scripts/herdr-rails.mjs",
351
359
  ) &&
352
360
  !/from\s+"\.\/(mux-|entwurf-)/.test(code),
353
361
  );
@@ -165,6 +165,57 @@ async function main(): Promise<void> {
165
165
  piNativeSessionIdFromPath("/s/2026-09-14T05-17-03-979Z_not-a-uuid.jsonl") === null &&
166
166
  piNativeSessionIdFromPath(`/s/${PI_NATIVE}.jsonl`) === null,
167
167
  );
168
+ {
169
+ // THE VENDOR HALF OF THAT CLAIM, FROM THE INSTALLED VENDOR — not a literal we typed.
170
+ // The key this parser recovers lives inside a filename pi builds, so the rule is only as
171
+ // true as pi's naming, and a source read cannot settle whether that naming is a contract
172
+ // or a convention. `[측정 2026-09-22, @earendil-works/pi-coding-agent 0.87.0]` the installed
173
+ // `SessionManager` writes a REAL session file here, in a temp dir, with zero model, zero
174
+ // network and zero child process: `create()` then one `appendMessage` flushes
175
+ // `<stamp>_<id>.jsonl` whose own `{"type":"session"}` header carries the same id.
176
+ //
177
+ // The 0.86.0 receipt this replaces needed a provider call and was therefore taken by hand
178
+ // once; it stays in the bump ledger as a 0.86.0 fact. This one re-takes itself on every
179
+ // run, so the vendor floor cannot drift under us silently again.
180
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "entwurf-hp-vendor-"));
181
+ try {
182
+ const { SessionManager } = await import("@earendil-works/pi-coding-agent");
183
+ const manager = await SessionManager.create(process.cwd(), dir);
184
+ await manager.appendMessage({
185
+ role: "assistant",
186
+ content: [{ type: "text", text: "placement vendor-floor probe" }],
187
+ api: "test",
188
+ provider: "test",
189
+ model: "test",
190
+ // Zero everything: this message exists to make the manager flush a file, and a
191
+ // fixture that invented usage numbers would be inventing vendor accounting too.
192
+ usage: {
193
+ input: 0,
194
+ output: 0,
195
+ cacheRead: 0,
196
+ cacheWrite: 0,
197
+ totalTokens: 0,
198
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
199
+ },
200
+ stopReason: "stop",
201
+ timestamp: Date.now(),
202
+ });
203
+ const written = fs.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
204
+ const header = JSON.parse(readFileSync(path.join(dir, written[0]), "utf8").split("\n")[0]);
205
+ const recovered = piNativeSessionIdFromPath(path.join(dir, written[0]));
206
+ ok(
207
+ "the vendor floor is re-measured, not remembered: the installed pi writes a real session file whose " +
208
+ "basename this parser reads back to the same id its own header declares",
209
+ written.length === 1 &&
210
+ header.type === "session" &&
211
+ typeof header.id === "string" &&
212
+ recovered === header.id &&
213
+ recovered === manager.getSessionId(),
214
+ );
215
+ } finally {
216
+ fs.rmSync(dir, { recursive: true, force: true });
217
+ }
218
+ }
168
219
  ok(
169
220
  "[QK:HP-JOIN-NEVER-GUESSES] an unmeasured agent_session kind and an empty value both yield NO key — an " +
170
221
  "unknown herdr shape is declined, never coerced into one of the two rules we actually measured",
@@ -33,6 +33,7 @@ import fs from "node:fs";
33
33
  import os from "node:os";
34
34
  import path from "node:path";
35
35
  import { pathToFileURL } from "node:url";
36
+ import * as HERDR_RAILS from "./herdr-rails.mjs";
36
37
  import { reclaimOnExit } from "./lib/reclaim-on-exit.ts";
37
38
  import { treeDigest } from "./lib/tree-digest.ts";
38
39
 
@@ -769,17 +770,23 @@ function drive(
769
770
  // contains `claude-sonnet-5`, so a containment test cannot tell the two grammars apart —
770
771
  // which is the whole claim.
771
772
  const idIn = (lines: string[], backend: string): string | null => {
772
- const line = lines.find((l) => l.startsWith(`note: ${backend}: `) && l.includes("model id looks like"));
773
+ const line = lines.find((l) => l.startsWith(`note: ${backend}: `) && l.includes("model string looks like"));
773
774
  return line === undefined ? null : (/`([^`]+)`/.exec(line)?.[1] ?? null);
774
775
  };
775
776
  const piId = idIn(notesOf(full), "pi");
776
777
  const claudeId = idIn(notesOf(full), "claude-code");
777
778
  return (
778
- piId === "openai-codex/gpt-5.6-terra" &&
779
+ // Compared against the SHARED leaf, not a literal copied into this gate: the install
780
+ // narration and the status pane's RAILS block now read one declaration
781
+ // (`scripts/herdr-rails.mjs`, #116 A7), and a gate holding its own third copy would
782
+ // be the very drift that leaf exists to stop. The GRAMMAR assertions stay literal —
783
+ // provider-qualified vs bare vendor id is the fact, and it must not become whatever
784
+ // the leaf happens to say.
785
+ piId === HERDR_RAILS.MODEL_SYNTAX_EXAMPLE.pi &&
779
786
  piId.includes("/") &&
780
- claudeId === "claude-sonnet-5" &&
787
+ claudeId === HERDR_RAILS.MODEL_SYNTAX_EXAMPLE["claude-code"] &&
781
788
  !claudeId.includes("/") &&
782
- idIn(notesOf(piOnly), "pi") === "openai-codex/gpt-5.6-terra" &&
789
+ idIn(notesOf(piOnly), "pi") === HERDR_RAILS.MODEL_SYNTAX_EXAMPLE.pi &&
783
790
  idIn(notesOf(piOnly), "claude-code") === null
784
791
  );
785
792
  })(),