@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.
Files changed (183) hide show
  1. package/AGENTS.md +240 -0
  2. package/BASELINE.md +227 -0
  3. package/CHANGELOG.md +1210 -0
  4. package/CONTRIBUTING.md +63 -0
  5. package/DELIVERY.md +209 -0
  6. package/LICENSE +21 -0
  7. package/README.md +504 -0
  8. package/VERIFY.md +260 -0
  9. package/demo/README.md +188 -0
  10. package/demo/demo-baseline.sh +156 -0
  11. package/demo/demo.sh +183 -0
  12. package/docs/assets/entwurf-demo.gif +0 -0
  13. package/docs/assets/entwurf-doomemacs.gif +0 -0
  14. package/docs/assets/entwurf-entwurf.gif +0 -0
  15. package/docs/assets/entwurf-hero.jpg +0 -0
  16. package/docs/setup-clean-host.md +305 -0
  17. package/mcp/entwurf-bridge/src/index.ts +513 -0
  18. package/mcp/entwurf-bridge/start.sh +25 -0
  19. package/mcp/entwurf-bridge/test.sh +54 -0
  20. package/mcp/tsconfig.json +29 -0
  21. package/package.json +130 -0
  22. package/pi/entwurf-capabilities.json +9 -0
  23. package/pi/entwurf-targets.json +20 -0
  24. package/pi/meta-bridge/.claude-plugin/marketplace.json +12 -0
  25. package/pi/meta-bridge/entwurf-meta-receive/.claude-plugin/plugin.json +5 -0
  26. package/pi/meta-bridge/entwurf-meta-receive/hooks/hooks.json +50 -0
  27. package/pi/meta-bridge/entwurf-meta-receive/scripts/doorbell.sh +54 -0
  28. package/pi/settings.reference.json +43 -0
  29. package/pi/skill-plugin-example/.claude-plugin/plugin.json +4 -0
  30. package/pi/skill-plugin-example/skills/hello/SKILL.md +18 -0
  31. package/pi-extensions/acp-provider.ts +63 -0
  32. package/pi-extensions/entwurf-control.ts +1692 -0
  33. package/pi-extensions/lib/acp/acp-client.ts +90 -0
  34. package/pi-extensions/lib/acp/augment.ts +238 -0
  35. package/pi-extensions/lib/acp/backend-adapter.ts +319 -0
  36. package/pi-extensions/lib/acp/backend.ts +873 -0
  37. package/pi-extensions/lib/acp/config.ts +552 -0
  38. package/pi-extensions/lib/acp/context.ts +177 -0
  39. package/pi-extensions/lib/acp/engraving.ts +123 -0
  40. package/pi-extensions/lib/acp/event-mapper.ts +339 -0
  41. package/pi-extensions/lib/acp/models.ts +102 -0
  42. package/pi-extensions/lib/acp/overlay.ts +220 -0
  43. package/pi-extensions/lib/acp/prompts/engraving.md +1 -0
  44. package/pi-extensions/lib/acp/session-store.ts +418 -0
  45. package/pi-extensions/lib/acp/tool-surface.ts +184 -0
  46. package/pi-extensions/lib/entwurf-control-rpc.ts +208 -0
  47. package/pi-extensions/lib/entwurf-core.ts +2033 -0
  48. package/pi-extensions/lib/entwurf-deliverability.ts +123 -0
  49. package/pi-extensions/lib/entwurf-fact-provider.ts +158 -0
  50. package/pi-extensions/lib/entwurf-facts.ts +251 -0
  51. package/pi-extensions/lib/entwurf-mailbox-guard.ts +100 -0
  52. package/pi-extensions/lib/entwurf-peers-render.ts +154 -0
  53. package/pi-extensions/lib/entwurf-preflight.ts +247 -0
  54. package/pi-extensions/lib/entwurf-resume-args.ts +88 -0
  55. package/pi-extensions/lib/entwurf-self-address.ts +117 -0
  56. package/pi-extensions/lib/entwurf-v2-contract.ts +427 -0
  57. package/pi-extensions/lib/entwurf-v2-decider.ts +441 -0
  58. package/pi-extensions/lib/entwurf-v2-lock.ts +412 -0
  59. package/pi-extensions/lib/entwurf-v2-mailbox.ts +87 -0
  60. package/pi-extensions/lib/entwurf-v2-production.ts +326 -0
  61. package/pi-extensions/lib/entwurf-v2-release.ts +149 -0
  62. package/pi-extensions/lib/entwurf-v2-resume-marker.ts +34 -0
  63. package/pi-extensions/lib/entwurf-v2-runner.ts +196 -0
  64. package/pi-extensions/lib/entwurf-v2-send-fallback.ts +166 -0
  65. package/pi-extensions/lib/entwurf-v2-send.ts +271 -0
  66. package/pi-extensions/lib/entwurf-v2-spawn-production.ts +337 -0
  67. package/pi-extensions/lib/entwurf-v2-spawn.ts +323 -0
  68. package/pi-extensions/lib/entwurf-v2-surface.ts +205 -0
  69. package/pi-extensions/lib/meta-mailbox-body.ts +80 -0
  70. package/pi-extensions/lib/meta-session.ts +1951 -0
  71. package/pi-extensions/lib/project-trust-handler.ts +154 -0
  72. package/pi-extensions/lib/session-id.js +57 -0
  73. package/pi-extensions/lib/socket-discovery.ts +346 -0
  74. package/pi-extensions/lib/socket-probe.ts +92 -0
  75. package/pi-extensions/meta-bridge-hook.ts +250 -0
  76. package/pi-extensions/model-lock.ts +235 -0
  77. package/prompts/engraving.md +27 -0
  78. package/protocol.js +31 -0
  79. package/run.sh +2832 -0
  80. package/scripts/check-acp-backend-preflight.ts +130 -0
  81. package/scripts/check-acp-carrier-augment.ts +297 -0
  82. package/scripts/check-acp-config.ts +322 -0
  83. package/scripts/check-acp-event-mapper.ts +253 -0
  84. package/scripts/check-acp-overlay.ts +154 -0
  85. package/scripts/check-acp-prompt-builder.ts +191 -0
  86. package/scripts/check-acp-provider-surface.ts +159 -0
  87. package/scripts/check-acp-sdk-surface.ts +211 -0
  88. package/scripts/check-acp-session-reuse.ts +756 -0
  89. package/scripts/check-acp-session-store.ts +387 -0
  90. package/scripts/check-acp-tool-surface.ts +159 -0
  91. package/scripts/check-entwurf-bridge-boot.ts +199 -0
  92. package/scripts/check-entwurf-capabilities.ts +123 -0
  93. package/scripts/check-entwurf-control-rpc.ts +187 -0
  94. package/scripts/check-entwurf-deliverability.ts +158 -0
  95. package/scripts/check-entwurf-fact-provider.ts +316 -0
  96. package/scripts/check-entwurf-facts.ts +358 -0
  97. package/scripts/check-entwurf-mailbox-guard.ts +264 -0
  98. package/scripts/check-entwurf-peers-surface.ts +235 -0
  99. package/scripts/check-entwurf-resume-args.ts +149 -0
  100. package/scripts/check-entwurf-self-address.ts +209 -0
  101. package/scripts/check-entwurf-session-identity.ts +703 -0
  102. package/scripts/check-entwurf-v2-contract.ts +536 -0
  103. package/scripts/check-entwurf-v2-decider.ts +795 -0
  104. package/scripts/check-entwurf-v2-lock.ts +368 -0
  105. package/scripts/check-entwurf-v2-mailbox.ts +228 -0
  106. package/scripts/check-entwurf-v2-matrix.ts +437 -0
  107. package/scripts/check-entwurf-v2-production.ts +406 -0
  108. package/scripts/check-entwurf-v2-release.ts +245 -0
  109. package/scripts/check-entwurf-v2-runner.ts +452 -0
  110. package/scripts/check-entwurf-v2-send-fallback.ts +371 -0
  111. package/scripts/check-entwurf-v2-send.ts +454 -0
  112. package/scripts/check-entwurf-v2-spawn-production.ts +452 -0
  113. package/scripts/check-entwurf-v2-spawn.ts +398 -0
  114. package/scripts/check-entwurf-v2-surface.ts +352 -0
  115. package/scripts/check-keyset-overlap.py +120 -0
  116. package/scripts/check-mailbox-receipt-state.ts +170 -0
  117. package/scripts/check-meta-capability-source.ts +112 -0
  118. package/scripts/check-meta-dual-consumers.ts +154 -0
  119. package/scripts/check-meta-dual-read.ts +158 -0
  120. package/scripts/check-meta-listing.ts +138 -0
  121. package/scripts/check-meta-mailbox-state-write.ts +135 -0
  122. package/scripts/check-meta-migration.ts +212 -0
  123. package/scripts/check-meta-receiver-marker.ts +185 -0
  124. package/scripts/check-meta-record-v2.ts +191 -0
  125. package/scripts/check-meta-session.ts +673 -0
  126. package/scripts/check-model-lock.ts +408 -0
  127. package/scripts/check-package-source-routing.ts +253 -0
  128. package/scripts/check-pi-preflight.ts +304 -0
  129. package/scripts/check-project-trust-handler.ts +265 -0
  130. package/scripts/check-shell-quote.ts +121 -0
  131. package/scripts/check-socket-discovery.ts +428 -0
  132. package/scripts/check-socket-probe.ts +106 -0
  133. package/scripts/fixtures/probe-mcp-server.ts +33 -0
  134. package/scripts/gnew-rpc-drive.ts +211 -0
  135. package/scripts/lib/acp-child-cleanup.ts +116 -0
  136. package/scripts/meta-bridge-doctor.sh +315 -0
  137. package/scripts/meta-bridge-hook-log.sh +26 -0
  138. package/scripts/meta-bridge-install.sh +135 -0
  139. package/scripts/meta-bridge-prune.ts +199 -0
  140. package/scripts/meta-bridge-state.py +549 -0
  141. package/scripts/meta-bridge-statusline.sh +192 -0
  142. package/scripts/meta-bridge-store-doctor.ts +64 -0
  143. package/scripts/meta-bridge-uninstall.sh +39 -0
  144. package/scripts/new-session-id.ts +25 -0
  145. package/scripts/postinstall-chmod.cjs +58 -0
  146. package/scripts/raw-async-delivery/README.md +258 -0
  147. package/scripts/raw-async-delivery/cc-enqueue-addressed.sh +35 -0
  148. package/scripts/raw-async-delivery/cc-mailbox-rewake.sh +38 -0
  149. package/scripts/raw-async-delivery/cc-watch-filechanged.sh +19 -0
  150. package/scripts/raw-async-delivery/cc-watch-sessionstart.sh +15 -0
  151. package/scripts/raw-async-delivery/codex-local-appserver.sh +39 -0
  152. package/scripts/raw-async-delivery/plugin-entwurf-receive/.claude-plugin/plugin.json +5 -0
  153. package/scripts/raw-async-delivery/plugin-entwurf-receive/hooks/hooks.json +28 -0
  154. package/scripts/raw-async-delivery/plugin-entwurf-receive/scripts/watch-filechanged.sh +28 -0
  155. package/scripts/raw-async-delivery/plugin-entwurf-receive/scripts/watch-sessionstart.sh +27 -0
  156. package/scripts/raw-async-delivery/raw-agy-send.sh +29 -0
  157. package/scripts/raw-async-delivery/raw-claude-enqueue.sh +30 -0
  158. package/scripts/raw-async-delivery/raw-codex-ws-turn-start.py +164 -0
  159. package/scripts/raw-async-delivery/repro-addressed-routing.sh +96 -0
  160. package/scripts/raw-async-delivery/repro-plugin-idle-wake.sh +104 -0
  161. package/scripts/resolve-acp-bridge.ts +25 -0
  162. package/scripts/smoke-acp-bundled-mcp-live.ts +292 -0
  163. package/scripts/smoke-acp-carrier-augment-live.ts +192 -0
  164. package/scripts/smoke-acp-mcp-live.ts +129 -0
  165. package/scripts/smoke-acp-memory-containment-live.ts +389 -0
  166. package/scripts/smoke-acp-overlay-live.ts +314 -0
  167. package/scripts/smoke-acp-provider-live.ts +162 -0
  168. package/scripts/smoke-acp-raw-turn-live.ts +261 -0
  169. package/scripts/smoke-acp-session-reuse-live.ts +172 -0
  170. package/scripts/smoke-acp-skill-live.ts +144 -0
  171. package/scripts/smoke-acp-socket-citizen-live.ts +168 -0
  172. package/scripts/smoke-claude-native-resume-live.sh +198 -0
  173. package/scripts/smoke-entwurf-v2-matrix-live.ts +398 -0
  174. package/scripts/smoke-entwurf-v2-spawn-live.ts +175 -0
  175. package/scripts/smoke-entwurf-v2-spawn-resume-live.ts +428 -0
  176. package/scripts/smoke-meta-async-drift.sh +171 -0
  177. package/scripts/smoke-meta-honesty.sh +147 -0
  178. package/scripts/smoke-meta-install-state.sh +403 -0
  179. package/scripts/smoke-meta-keyset-guard.sh +111 -0
  180. package/scripts/smoke-meta-prune.sh +174 -0
  181. package/scripts/smoke-resident-garden-guard.sh +433 -0
  182. package/scripts/smoke-session-id-name.ts +187 -0
  183. package/scripts/tsconfig.json +34 -0
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * meta-bridge-prune — LISTING-ONLY hygiene surface for the meta-session store.
4
+ *
5
+ * 1.0.0 policy (GLG + GPT힣, 2026-06-06): list candidates, NEVER delete. The
6
+ * store is the native→garden lookup authority, so this surface is deliberately
7
+ * conservative:
8
+ * - orphan (transcript gone) / stale (recordUpdatedAt older than ttl) are
9
+ * SUGGESTED for manual prune with the exact rm command printed — but removed
10
+ * by no one here. transcript-gone is a strong abandonment signal, not proof; a
11
+ * backend path migration / cleanup / config-dir change can also vacate it. A
12
+ * NULL transcriptPath (v2 nullable-at-birth, e.g. pi) is "unknown", NOT gone —
13
+ * never orphan on null; only a non-empty string path that no longer exists.
14
+ * - corrupt JSON / body↔filename drift / duplicate nativeSessionId are
15
+ * AMBIGUOUS / manual-only: the operator decides which authority survives.
16
+ * Never blindly rm a duplicate pair.
17
+ * No --apply in 1.0.0. The script prints, the operator removes. doctor stays the
18
+ * fail-loud surface (store-doctor reds on corrupt/duplicate/drift); prune is the
19
+ * separate janitor LISTING that keeps a green store from silently bloating with
20
+ * transcript-gone records — which doctor intentionally does NOT fail on.
21
+ */
22
+
23
+ import fs from "node:fs";
24
+ import path from "node:path";
25
+ import { defaultMetaSessionsDir, type MetaIdentity, parseMetaIdentity } from "../pi-extensions/lib/meta-session.ts";
26
+
27
+ /** POSIX single-quote a path so the printed rm command survives spaces/specials. */
28
+ function shellQuote(s: string): string {
29
+ return `'${s.replace(/'/g, "'\\''")}'`;
30
+ }
31
+
32
+ function usage(code: number): never {
33
+ console.error(
34
+ "usage: node --experimental-strip-types scripts/meta-bridge-prune.ts [meta-sessions-dir] [--ttl-days N]",
35
+ );
36
+ process.exit(code);
37
+ }
38
+
39
+ let dirArg: string | undefined;
40
+ let ttlDays = 30;
41
+ for (let i = 2; i < process.argv.length; i++) {
42
+ const a = process.argv[i];
43
+ if (a === "--ttl-days") {
44
+ const v = process.argv[++i];
45
+ const n = Number(v);
46
+ if (!Number.isFinite(n) || n < 0) usage(2);
47
+ ttlDays = n;
48
+ } else if (a.startsWith("--ttl-days=")) {
49
+ const n = Number(a.slice("--ttl-days=".length));
50
+ if (!Number.isFinite(n) || n < 0) usage(2);
51
+ ttlDays = n;
52
+ } else if (a === "-h" || a === "--help") {
53
+ usage(0);
54
+ } else if (a.startsWith("-")) {
55
+ console.error(`unknown flag: ${a}`);
56
+ usage(2);
57
+ } else if (dirArg === undefined) {
58
+ dirArg = a;
59
+ } else {
60
+ usage(2);
61
+ }
62
+ }
63
+
64
+ const dir = dirArg ?? defaultMetaSessionsDir();
65
+ const ttlMs = ttlDays * 24 * 60 * 60 * 1000;
66
+ const now = Date.now();
67
+
68
+ console.log("meta-bridge prune candidates");
69
+ console.log(`store: ${dir}`);
70
+ console.log(`ttl: ${ttlDays}d (stale threshold)`);
71
+ console.log("");
72
+
73
+ if (!fs.existsSync(dir)) {
74
+ console.log(`store does not exist yet (0 records).`);
75
+ console.log("");
76
+ console.log("No files removed.");
77
+ process.exit(0);
78
+ }
79
+
80
+ interface Good {
81
+ file: string;
82
+ gardenId: string;
83
+ backend: string;
84
+ nativeSessionId: string;
85
+ transcriptPath: string | null;
86
+ recordUpdatedAt: string;
87
+ }
88
+
89
+ const goodByNative = new Map<string, Good[]>();
90
+ const ambiguous: string[] = [];
91
+ let scanned = 0;
92
+
93
+ for (const filename of fs.readdirSync(dir).sort()) {
94
+ if (!filename.endsWith(".meta.json")) continue;
95
+ scanned += 1;
96
+ const file = path.join(dir, filename);
97
+ // dual-read (3D-4 commit1): parseMetaIdentity reads v1 AND v2, normalizing to
98
+ // identity (transcriptPath nullable, lastSeen → recordUpdatedAt).
99
+ let id: MetaIdentity;
100
+ try {
101
+ id = parseMetaIdentity(fs.readFileSync(file, "utf8"));
102
+ } catch (err) {
103
+ ambiguous.push(`${filename}: corrupt — ${err instanceof Error ? err.message : String(err)}`);
104
+ continue;
105
+ }
106
+ const expectedFilename = `${id.gardenId}.meta.json`;
107
+ if (filename !== expectedFilename) {
108
+ ambiguous.push(`${filename}: body/filename drift — body gardenId=${id.gardenId}, expected ${expectedFilename}`);
109
+ continue;
110
+ }
111
+ const list = goodByNative.get(id.nativeSessionId) ?? [];
112
+ list.push({
113
+ file: filename,
114
+ gardenId: id.gardenId,
115
+ backend: id.backend,
116
+ nativeSessionId: id.nativeSessionId,
117
+ transcriptPath: id.transcriptPath,
118
+ recordUpdatedAt: id.recordUpdatedAt,
119
+ });
120
+ goodByNative.set(id.nativeSessionId, list);
121
+ }
122
+
123
+ const orphan: Good[] = [];
124
+ const stale: Good[] = [];
125
+ let keep = 0;
126
+
127
+ for (const [nativeSessionId, list] of goodByNative.entries()) {
128
+ if (list.length > 1) {
129
+ // Authority ambiguity — operator must choose which survives. Never auto-pick.
130
+ ambiguous.push(
131
+ `duplicate nativeSessionId ${JSON.stringify(nativeSessionId)} in ${list.map((g) => g.file).join(", ")} — manual-only, do not blindly remove`,
132
+ );
133
+ continue;
134
+ }
135
+ const g = list[0];
136
+ // G2 (3D-4): null transcriptPath is NOT orphan. v2 (pi nullable-at-birth) leaves
137
+ // it null = "unknown / not yet known", which is not "the file went away". Orphan
138
+ // is ONLY a non-empty string path that no longer exists on disk. A null path
139
+ // falls through to the recordUpdatedAt staleness check like any live record.
140
+ const tp = g.transcriptPath;
141
+ if (typeof tp === "string" && tp !== "" && !fs.existsSync(tp)) {
142
+ orphan.push(g);
143
+ continue;
144
+ }
145
+ // recordUpdatedAt is only proven a non-empty string by the parser, not a real
146
+ // date. KEEP means live + RECENT; an unparseable recordUpdatedAt cannot prove
147
+ // recency, so it is not a silent keep — it goes manual-only like any defect.
148
+ const updatedMs = Date.parse(g.recordUpdatedAt);
149
+ if (!Number.isFinite(updatedMs)) {
150
+ ambiguous.push(
151
+ `${g.file}: unparseable recordUpdatedAt ${JSON.stringify(g.recordUpdatedAt)} — cannot prove recent, manual-only`,
152
+ );
153
+ continue;
154
+ }
155
+ if (now - updatedMs > ttlMs) stale.push(g);
156
+ else keep += 1;
157
+ }
158
+
159
+ const ageDays = (iso: string): string => {
160
+ const ms = now - Date.parse(iso);
161
+ if (!Number.isFinite(ms)) return "?";
162
+ return String(Math.floor(ms / (24 * 60 * 60 * 1000)));
163
+ };
164
+
165
+ console.log(`ORPHAN transcript-gone (${orphan.length}):`);
166
+ for (const g of orphan) {
167
+ console.log(`- ${g.gardenId} ${g.backend} native=${g.nativeSessionId} transcript=${g.transcriptPath ?? "(null)"}`);
168
+ }
169
+ console.log("");
170
+
171
+ console.log(`STALE recordUpdatedAt>${ttlDays}d (${stale.length}):`);
172
+ for (const g of stale) {
173
+ console.log(`- ${g.gardenId} ${g.backend} recordUpdatedAt=${g.recordUpdatedAt} age=${ageDays(g.recordUpdatedAt)}d`);
174
+ }
175
+ console.log("");
176
+
177
+ console.log(`AMBIGUOUS manual-only (${ambiguous.length}):`);
178
+ for (const reason of ambiguous) {
179
+ console.log(`- ${reason}`);
180
+ }
181
+ console.log("");
182
+
183
+ console.log(`KEEP (live/recent): ${keep} record(s)`);
184
+ console.log(`scanned: ${scanned} record(s)`);
185
+ console.log("");
186
+
187
+ console.log("No files removed.");
188
+ const removable = [...orphan, ...stale];
189
+ if (removable.length > 0) {
190
+ console.log("To prune an orphan/stale candidate, inspect it then remove its file manually:");
191
+ for (const g of removable) {
192
+ console.log(` rm -- ${shellQuote(path.join(dir, `${g.gardenId}.meta.json`))}`);
193
+ }
194
+ }
195
+ if (ambiguous.length > 0) {
196
+ console.log("AMBIGUOUS records are NOT listed as rm commands — inspect each and decide which authority survives.");
197
+ }
198
+
199
+ process.exit(0);