@junghanacs/entwurf 0.12.2 → 0.12.4
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 +2 -2
- package/CHANGELOG.md +39 -0
- package/README.md +9 -5
- package/VERIFY.md +4 -4
- package/demo/README.md +5 -5
- package/demo/demo-baseline.sh +2 -2
- package/demo/demo.sh +3 -3
- package/docs/setup-clean-host.md +27 -10
- package/mcp/entwurf-bridge/dist/scripts/meta-bridge-store-doctor.js +55 -0
- package/mcp/entwurf-bridge/tsconfig.build.json +14 -6
- package/package.json +9 -9
- package/pi/entwurf-targets.json +3 -6
- package/pi-extensions/lib/acp/acp-client.ts +2 -2
- package/pi-extensions/lib/acp/models.ts +7 -9
- package/run.sh +74 -21
- package/scripts/check-acp-backend-preflight.ts +1 -1
- package/scripts/check-acp-config.ts +3 -3
- package/scripts/check-acp-event-mapper.ts +1 -1
- package/scripts/check-acp-provider-surface.ts +1 -1
- package/scripts/check-acp-sdk-surface.ts +22 -22
- package/scripts/check-acp-session-reuse.ts +3 -3
- package/scripts/check-acp-session-store.ts +6 -6
- package/scripts/check-acp-tool-surface.ts +2 -2
- package/scripts/check-entwurf-session-identity.ts +9 -9
- package/scripts/check-model-lock.ts +2 -2
- package/scripts/check-package-source-routing.ts +4 -4
- package/scripts/meta-bridge-doctor.sh +55 -10
- package/scripts/meta-bridge-state.py +2 -0
- package/scripts/resolve-acp-bridge.ts +1 -1
- package/scripts/smoke-acp-bundled-mcp-live.ts +1 -1
- package/scripts/smoke-acp-carrier-augment-live.ts +1 -1
- package/scripts/smoke-acp-mcp-live.ts +1 -1
- package/scripts/smoke-acp-memory-containment-live.ts +8 -9
- package/scripts/smoke-acp-overlay-live.ts +8 -9
- package/scripts/smoke-acp-provider-live.ts +1 -1
- package/scripts/smoke-acp-raw-turn-live.ts +12 -11
- package/scripts/smoke-acp-session-reuse-live.ts +24 -9
- package/scripts/smoke-acp-skill-live.ts +1 -1
- package/scripts/smoke-meta-install-state.sh +3 -3
|
@@ -117,7 +117,7 @@ PY
|
|
|
117
117
|
EXPECTED_STATUSLINE="$REPO/scripts/meta-bridge-statusline.sh"
|
|
118
118
|
if [ "$STATUSLINE_CMD" = "$EXPECTED_STATUSLINE" ]; then ok "statusLine.command is repo-owned: $STATUSLINE_CMD"; else bad "statusLine.command drifted (got '$STATUSLINE_CMD', expected '$EXPECTED_STATUSLINE')"; fi
|
|
119
119
|
if [ -x "$EXPECTED_STATUSLINE" ]; then ok "statusline executable"; else bad "statusline script not executable: $EXPECTED_STATUSLINE"; fi
|
|
120
|
-
SAMPLE_STATUSLINE_OUT="$(printf '%s' '{"session_id":"doctor-no-record","workspace":{"current_dir":"/tmp"},"model":{"id":"claude-sonnet-
|
|
120
|
+
SAMPLE_STATUSLINE_OUT="$(printf '%s' '{"session_id":"doctor-no-record","workspace":{"current_dir":"/tmp"},"model":{"id":"claude-sonnet-5"},"context_window":{"context_window_size":200000,"used_percentage":1,"current_usage":{"input_tokens":1}}}' | "$EXPECTED_STATUSLINE" 2>/dev/null || true)"
|
|
121
121
|
if [ "$(printf '%s\n' "$SAMPLE_STATUSLINE_OUT" | wc -l | tr -d ' ')" = "2" ] && printf '%s\n' "$SAMPLE_STATUSLINE_OUT" | sed -n '1p' | grep -q 'tmp' && printf '%s\n' "$SAMPLE_STATUSLINE_OUT" | sed -n '2p' | grep -q '🪛' && printf '%s\n' "$SAMPLE_STATUSLINE_OUT" | sed -n '2p' | grep -q ' cc | s'; then ok "statusline synthetic execution emits two rows (work context + identity)"; else bad "statusline synthetic execution failed or omitted two-row work/identity marker"; fi
|
|
122
122
|
else
|
|
123
123
|
bad "cannot validate statusline without python3"
|
|
@@ -147,10 +147,36 @@ echo "[meta-record store]"
|
|
|
147
147
|
mkdir -p "$META_SESSIONS" 2>/dev/null || true
|
|
148
148
|
if [ -d "$META_SESSIONS" ] && [ -w "$META_SESSIONS" ]; then ok "writable: $META_SESSIONS"; else bad "meta-sessions dir not writable: $META_SESSIONS"; fi
|
|
149
149
|
if command -v node >/dev/null; then
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
# Full store scan — mode by LOCATION (mirror mcp/entwurf-bridge/start.sh). Node
|
|
151
|
+
# REFUSES --experimental-strip-types for a .ts under node_modules
|
|
152
|
+
# (ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING), so an INSTALLED package must scan
|
|
153
|
+
# via the prebuilt dist JS (build-bridge emits it; files:["mcp/"] ships it); a DEV
|
|
154
|
+
# CLONE lives outside node_modules and runs the .ts source. Before this split the
|
|
155
|
+
# doctor always ran the .ts and reported a FALSE "corrupt records" FAIL on every
|
|
156
|
+
# installed host (the 0.12.0 strip-types-under-node_modules class the bridge boot
|
|
157
|
+
# already fixed, but this doctor helper still ran raw .ts).
|
|
158
|
+
case "$REPO" in
|
|
159
|
+
*/node_modules/*)
|
|
160
|
+
store_doctor="$REPO/mcp/entwurf-bridge/dist/scripts/meta-bridge-store-doctor.js"
|
|
161
|
+
if [ -f "$store_doctor" ]; then
|
|
162
|
+
store_scan=(node "$store_doctor" "$META_SESSIONS")
|
|
163
|
+
else
|
|
164
|
+
bad "installed under node_modules but prebuilt store-doctor missing: $store_doctor — the tarball ships it via prepack; reinstall @junghanacs/entwurf"
|
|
165
|
+
store_scan=()
|
|
166
|
+
fi
|
|
167
|
+
;;
|
|
168
|
+
*)
|
|
169
|
+
store_scan=(node --experimental-strip-types "$REPO/scripts/meta-bridge-store-doctor.ts" "$META_SESSIONS")
|
|
170
|
+
;;
|
|
171
|
+
esac
|
|
172
|
+
# Guard the expansion: bash 3.2 (macOS) + set -u errors on "${arr[@]}" for a
|
|
173
|
+
# zero-length array, so only run/print when the command was actually built.
|
|
174
|
+
if [ "${#store_scan[@]}" -gt 0 ]; then
|
|
175
|
+
if "${store_scan[@]}" >/dev/null 2>&1; then
|
|
176
|
+
ok "full store scan: no corrupt records, duplicate nativeSessionId, body/filename drift, or backend↔wakeMode contradiction"
|
|
177
|
+
else
|
|
178
|
+
bad "full store scan failed — corrupt/duplicate/drift meta-record(s) present. Inspect with: ${store_scan[*]}"
|
|
179
|
+
fi
|
|
154
180
|
fi
|
|
155
181
|
else
|
|
156
182
|
bad "cannot scan meta-record store without node"
|
|
@@ -297,11 +323,30 @@ if [ -f "$V2_MCP_SRC" ] && grep -q 'server.tool(' "$V2_MCP_SRC" && grep -q '"ent
|
|
|
297
323
|
else
|
|
298
324
|
bad "MCP entwurf_v2 verb not found in entwurf-bridge"
|
|
299
325
|
fi
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
326
|
+
# check-entwurf-v2-surface is a SOURCE-SHAPE gate: it strip-types-runs a .ts gate
|
|
327
|
+
# (which imports typebox, a dev dep) to assert the surface source shape. Under
|
|
328
|
+
# node_modules that cannot run (strip-types refused + dev deps absent), AND its
|
|
329
|
+
# subject — the shipped surface source shape — is a repo/release invariant already
|
|
330
|
+
# enforced by the release gate. So on an INSTALLED host, confirm the surface source
|
|
331
|
+
# SHIPPED and defer the exhaustive gate; the live runtime wiring (flag/tool/MCP verb)
|
|
332
|
+
# is already proven by the grep checks just above. Running the full .ts gate here
|
|
333
|
+
# produced a FALSE "gate FAILED" on every installed host.
|
|
334
|
+
case "$REPO" in
|
|
335
|
+
*/node_modules/*)
|
|
336
|
+
if [ -f "$V2_SURFACE_SRC" ]; then
|
|
337
|
+
ok "check-entwurf-v2-surface: shipped surface source present; exhaustive source-shape gate is a repo/release invariant (not run under node_modules)"
|
|
338
|
+
else
|
|
339
|
+
bad "entwurf-v2-surface.ts missing from the installed package — the v2 surface source did not ship"
|
|
340
|
+
fi
|
|
341
|
+
;;
|
|
342
|
+
*)
|
|
343
|
+
if [ -f "$V2_SURFACE_SRC" ] && (cd "$REPO" && node --experimental-strip-types scripts/check-entwurf-v2-surface.ts >/dev/null 2>&1); then
|
|
344
|
+
ok "check-entwurf-v2-surface gate passes (surface adapter + pi-native/MCP wiring)"
|
|
345
|
+
else
|
|
346
|
+
bad "check-entwurf-v2-surface gate FAILED or surface adapter missing — run: ./run.sh check-entwurf-v2-surface"
|
|
347
|
+
fi
|
|
348
|
+
;;
|
|
349
|
+
esac
|
|
305
350
|
# prefixRoots operator policy (5d-4b): the shared env SSOT both v2 surfaces read. Display
|
|
306
351
|
# ONLY — the parser SSOT lives in entwurf-v2-surface.ts (proven by check-entwurf-v2-surface);
|
|
307
352
|
# the doctor does NOT re-implement parsing. Unset ⇒ no prefix promotion (the safe default).
|
|
@@ -80,6 +80,8 @@ MANAGED_SETTINGS_SCALARS: list[tuple[str, list[str], Any]] = [
|
|
|
80
80
|
("showTurnDuration", ["showTurnDuration"], False),
|
|
81
81
|
("terminalProgressBarEnabled", ["terminalProgressBarEnabled"], False),
|
|
82
82
|
("useAutoModeDuringPlan", ["useAutoModeDuringPlan"], False),
|
|
83
|
+
("enableWorkflows", ["enableWorkflows"], False),
|
|
84
|
+
("workflowKeywordTriggerEnabled", ["workflowKeywordTriggerEnabled"], False),
|
|
83
85
|
]
|
|
84
86
|
|
|
85
87
|
|
|
@@ -16,7 +16,7 @@ import type { ResolvedTarget } from "../pi-extensions/lib/entwurf-core.ts";
|
|
|
16
16
|
import { getRegistryRouting } from "../pi-extensions/lib/entwurf-core.ts";
|
|
17
17
|
|
|
18
18
|
const isRemote = process.argv[2] === "remote";
|
|
19
|
-
const target: ResolvedTarget = { provider: "entwurf", model: "claude-sonnet-
|
|
19
|
+
const target: ResolvedTarget = { provider: "entwurf", model: "claude-sonnet-5", explicitOnly: false };
|
|
20
20
|
|
|
21
21
|
// Throws EntwurfRoutingError (non-zero exit) when the bridge cannot be resolved —
|
|
22
22
|
// exactly the fail-fast the smoke wants to observe as a failure, not a pass.
|
|
@@ -46,7 +46,7 @@ import { generateSessionId } from "../pi-extensions/lib/entwurf-core.ts";
|
|
|
46
46
|
import { terminateChild } from "./lib/acp-child-cleanup.ts";
|
|
47
47
|
|
|
48
48
|
const ACP_PROVIDER = "entwurf";
|
|
49
|
-
const ACP_MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-
|
|
49
|
+
const ACP_MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-5";
|
|
50
50
|
|
|
51
51
|
const REAL_CONTROL_DIR = path.join(os.homedir(), ".pi", "entwurf-control");
|
|
52
52
|
const SOCKET_SUFFIX = ".sock";
|
|
@@ -47,7 +47,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
47
47
|
import { fileURLToPath } from "node:url";
|
|
48
48
|
|
|
49
49
|
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
50
|
-
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-
|
|
50
|
+
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-5";
|
|
51
51
|
const PROVIDER = "entwurf";
|
|
52
52
|
const TURN_TIMEOUT_MS = Number(process.env.ENTWURF_ACP_PROVIDER_TIMEOUT_MS) || 240_000;
|
|
53
53
|
|
|
@@ -29,7 +29,7 @@ import { fileURLToPath } from "node:url";
|
|
|
29
29
|
|
|
30
30
|
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
31
31
|
const PROBE_SERVER = join(REPO_ROOT, "scripts", "fixtures", "probe-mcp-server.ts");
|
|
32
|
-
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-
|
|
32
|
+
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-5";
|
|
33
33
|
const PROVIDER = "entwurf";
|
|
34
34
|
const TURN_TIMEOUT_MS = Number(process.env.ENTWURF_ACP_PROVIDER_TIMEOUT_MS) || 240_000;
|
|
35
35
|
|
|
@@ -69,7 +69,7 @@ import {
|
|
|
69
69
|
} from "../pi-extensions/lib/acp/tool-surface.ts";
|
|
70
70
|
import { terminateChild } from "./lib/acp-child-cleanup.ts";
|
|
71
71
|
|
|
72
|
-
const REQUESTED_MODEL_ID = process.env.ENTWURF_ACP_MEMORY_MODEL ?? "claude-sonnet-
|
|
72
|
+
const REQUESTED_MODEL_ID = process.env.ENTWURF_ACP_MEMORY_MODEL ?? "claude-sonnet-5";
|
|
73
73
|
const ALLOW_PATH_FALLBACK = process.env.ENTWURF_ACP_MEMORY_ALLOW_PATH_FALLBACK === "1";
|
|
74
74
|
const RAW_TAIL_CAP = 64 * 1024;
|
|
75
75
|
|
|
@@ -78,15 +78,14 @@ function fail(msg: string): never {
|
|
|
78
78
|
process.exit(1);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
|
|
82
|
-
|
|
83
81
|
function withTimeout<T>(label: string, p: Promise<T>, ms: number): Promise<T> {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
83
|
+
const timeout = new Promise<never>((_, reject) => {
|
|
84
|
+
timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
85
|
+
});
|
|
86
|
+
return Promise.race([p, timeout]).finally(() => {
|
|
87
|
+
if (timer) clearTimeout(timer);
|
|
88
|
+
});
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
/** Recursively list files under `dir` whose path contains a `memory` segment. */
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
} from "../pi-extensions/lib/acp/tool-surface.ts";
|
|
57
57
|
import { terminateChild } from "./lib/acp-child-cleanup.ts";
|
|
58
58
|
|
|
59
|
-
const REQUESTED_MODEL_ID = process.env.ENTWURF_ACP_OVERLAY_MODEL ?? "claude-sonnet-
|
|
59
|
+
const REQUESTED_MODEL_ID = process.env.ENTWURF_ACP_OVERLAY_MODEL ?? "claude-sonnet-5";
|
|
60
60
|
const ALLOW_PATH_FALLBACK = process.env.ENTWURF_ACP_OVERLAY_ALLOW_PATH_FALLBACK === "1";
|
|
61
61
|
const RAW_TAIL_CAP = 64 * 1024;
|
|
62
62
|
|
|
@@ -65,15 +65,14 @@ function fail(msg: string): never {
|
|
|
65
65
|
process.exit(1);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
|
|
69
|
-
|
|
70
68
|
function withTimeout<T>(label: string, p: Promise<T>, ms: number): Promise<T> {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
70
|
+
const timeout = new Promise<never>((_, reject) => {
|
|
71
|
+
timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
72
|
+
});
|
|
73
|
+
return Promise.race([p, timeout]).finally(() => {
|
|
74
|
+
if (timer) clearTimeout(timer);
|
|
75
|
+
});
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
if (process.env.LIVE !== "1") {
|
|
@@ -28,7 +28,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
28
28
|
import { fileURLToPath } from "node:url";
|
|
29
29
|
|
|
30
30
|
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
31
|
-
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-
|
|
31
|
+
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-5";
|
|
32
32
|
const PROVIDER = "entwurf";
|
|
33
33
|
const TURN_TIMEOUT_MS = Number(process.env.ENTWURF_ACP_PROVIDER_TIMEOUT_MS) || 240_000;
|
|
34
34
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// LIVE=1 ./run.sh smoke-acp-raw-turn-live
|
|
4
4
|
//
|
|
5
5
|
// What this proves (and ONLY this): the pinned Claude ACP adapter
|
|
6
|
-
// (@agentclientprotocol/claude-agent-acp@0.
|
|
6
|
+
// (@agentclientprotocol/claude-agent-acp@0.54.1) spawns, speaks the ACP wire
|
|
7
7
|
// protocol over stdio NDJSON, and returns one real model turn. It is the
|
|
8
8
|
// bytes-flow proof that the S2a dep surface is not just installable but
|
|
9
9
|
// actually drivable — before any provider/overlay/streamSimple code (S2b+).
|
|
@@ -35,7 +35,7 @@ import { ndJsonStream, PROTOCOL_VERSION } from "@agentclientprotocol/sdk";
|
|
|
35
35
|
import { connectAcpClient } from "../pi-extensions/lib/acp/acp-client.ts";
|
|
36
36
|
import { terminateChild } from "./lib/acp-child-cleanup.ts";
|
|
37
37
|
|
|
38
|
-
const REQUESTED_MODEL_ID = process.env.ENTWURF_ACP_RAW_TURN_MODEL ?? "claude-sonnet-
|
|
38
|
+
const REQUESTED_MODEL_ID = process.env.ENTWURF_ACP_RAW_TURN_MODEL ?? "claude-sonnet-5";
|
|
39
39
|
const ALLOW_PATH_FALLBACK = process.env.ENTWURF_ACP_RAW_TURN_ALLOW_PATH_FALLBACK === "1";
|
|
40
40
|
const RAW_TAIL_CAP = 64 * 1024; // cap captured raw NDJSON to 64KB tail on report.
|
|
41
41
|
|
|
@@ -44,17 +44,18 @@ function fail(msg: string): never {
|
|
|
44
44
|
process.exit(1);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
|
|
48
|
-
|
|
49
47
|
// Guard each RPC so a hung backend fails this smoke instead of the outer
|
|
50
|
-
// process timeout — keeps the failure attributable to the right step.
|
|
48
|
+
// process timeout — keeps the failure attributable to the right step. Always
|
|
49
|
+
// clear the timeout; otherwise a successful live turn can print PASS and keep
|
|
50
|
+
// Node alive until the stale timer fires.
|
|
51
51
|
function withTimeout<T>(label: string, p: Promise<T>, ms: number): Promise<T> {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
53
|
+
const timeout = new Promise<never>((_, reject) => {
|
|
54
|
+
timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
55
|
+
});
|
|
56
|
+
return Promise.race([p, timeout]).finally(() => {
|
|
57
|
+
if (timer) clearTimeout(timer);
|
|
58
|
+
});
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
if (process.env.LIVE !== "1") {
|
|
@@ -27,7 +27,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
27
27
|
import type { Api, AssistantMessageEvent, Context, Model } from "@earendil-works/pi-ai";
|
|
28
28
|
|
|
29
29
|
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
30
|
-
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-
|
|
30
|
+
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-5";
|
|
31
31
|
const TURN_TIMEOUT_MS = Number(process.env.ENTWURF_ACP_PROVIDER_TIMEOUT_MS) || 240_000;
|
|
32
32
|
|
|
33
33
|
function fail(msg: string): never {
|
|
@@ -35,6 +35,16 @@ function fail(msg: string): never {
|
|
|
35
35
|
process.exit(1);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
function withTimeout<T>(label: string, p: Promise<T>, ms: number): Promise<T> {
|
|
39
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
40
|
+
const timeout = new Promise<never>((_, reject) => {
|
|
41
|
+
timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
42
|
+
});
|
|
43
|
+
return Promise.race([p, timeout]).finally(() => {
|
|
44
|
+
if (timer) clearTimeout(timer);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
38
48
|
if (process.env.LIVE !== "1") {
|
|
39
49
|
console.error("[smoke-acp-session-reuse-live] skipped — set LIVE=1 to run the real 2-turn reuse acceptance.");
|
|
40
50
|
process.exit(0);
|
|
@@ -100,13 +110,15 @@ async function main(): Promise<void> {
|
|
|
100
110
|
},
|
|
101
111
|
],
|
|
102
112
|
};
|
|
103
|
-
const r1 = await
|
|
113
|
+
const r1 = await withTimeout(
|
|
114
|
+
"turn 1",
|
|
104
115
|
consume(backend.streamShellAcp(model, turn1, options) as Stream),
|
|
105
|
-
|
|
106
|
-
|
|
116
|
+
TURN_TIMEOUT_MS,
|
|
117
|
+
);
|
|
107
118
|
if (r1.error) fail(`turn 1 errored: ${r1.error}`);
|
|
108
119
|
if (!r1.done) fail("turn 1 did not complete");
|
|
109
120
|
console.error(`[smoke-acp-session-reuse-live] turn 1 reply: ${JSON.stringify(r1.text.slice(-120))}`);
|
|
121
|
+
console.error("[smoke-acp-session-reuse-live] starting turn 2 reuse prompt");
|
|
110
122
|
|
|
111
123
|
// --- turn 2 (reuse): ask for the codeword, DELTA ONLY ---
|
|
112
124
|
const turn2: Context = {
|
|
@@ -136,10 +148,11 @@ async function main(): Promise<void> {
|
|
|
136
148
|
},
|
|
137
149
|
],
|
|
138
150
|
};
|
|
139
|
-
const r2 = await
|
|
151
|
+
const r2 = await withTimeout(
|
|
152
|
+
"turn 2",
|
|
140
153
|
consume(backend.streamShellAcp(model, turn2, options) as Stream),
|
|
141
|
-
|
|
142
|
-
|
|
154
|
+
TURN_TIMEOUT_MS,
|
|
155
|
+
);
|
|
143
156
|
if (r2.error) fail(`turn 2 errored: ${r2.error}`);
|
|
144
157
|
if (!r2.done) fail("turn 2 did not complete");
|
|
145
158
|
console.error(`[smoke-acp-session-reuse-live] turn 2 reply: ${JSON.stringify(r2.text.slice(-120))}`);
|
|
@@ -160,8 +173,10 @@ async function main(): Promise<void> {
|
|
|
160
173
|
|
|
161
174
|
main()
|
|
162
175
|
.then(() => {
|
|
163
|
-
//
|
|
164
|
-
|
|
176
|
+
// Let stdout/stderr and finally cleanup drain naturally; the backend's process
|
|
177
|
+
// 'exit' hook still SIGKILLs the retained child when Node exits. A direct
|
|
178
|
+
// process.exit(0) can truncate the success/PASS log after the live turn.
|
|
179
|
+
process.exitCode = 0;
|
|
165
180
|
})
|
|
166
181
|
.catch((err) => {
|
|
167
182
|
fail(err instanceof Error ? err.message : String(err));
|
|
@@ -30,7 +30,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
30
30
|
import { fileURLToPath } from "node:url";
|
|
31
31
|
|
|
32
32
|
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
33
|
-
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-
|
|
33
|
+
const MODEL = process.env.ENTWURF_ACP_PROVIDER_MODEL?.trim() || "claude-sonnet-5";
|
|
34
34
|
const PROVIDER = "entwurf";
|
|
35
35
|
const TURN_TIMEOUT_MS = Number(process.env.ENTWURF_ACP_PROVIDER_TIMEOUT_MS) || 240_000;
|
|
36
36
|
|
|
@@ -102,7 +102,7 @@ assert settings['cleanupPeriodDays'] == 365
|
|
|
102
102
|
assert settings['env']['DISABLE_AUTOCOMPACT'] == '1'
|
|
103
103
|
assert settings['env']['KEEP_ME'] == 'yes'
|
|
104
104
|
assert settings['statusLine']['command'] == os.environ['REPO'] + '/scripts/meta-bridge-statusline.sh'
|
|
105
|
-
for key in ['promptSuggestionEnabled','awaySummaryEnabled','autoMemoryEnabled','verbose','autoCompactEnabled','showTurnDuration','terminalProgressBarEnabled','useAutoModeDuringPlan']:
|
|
105
|
+
for key in ['promptSuggestionEnabled','awaySummaryEnabled','autoMemoryEnabled','verbose','autoCompactEnabled','showTurnDuration','terminalProgressBarEnabled','useAutoModeDuringPlan','enableWorkflows','workflowKeywordTriggerEnabled']:
|
|
106
106
|
assert settings[key] is False, key
|
|
107
107
|
assert settings['skipDangerousModePermissionPrompt'] is True
|
|
108
108
|
for item in ['Bash','Read','Write','Edit','Grep','Glob','WebFetch','WebSearch','Skill','mcp__entwurf-bridge__*']:
|
|
@@ -192,7 +192,7 @@ assert settings['statusLine']['command'] == '/old/user/statusline.sh'
|
|
|
192
192
|
assert settings['promptSuggestionEnabled'] is True
|
|
193
193
|
assert settings['skipDangerousModePermissionPrompt'] is False
|
|
194
194
|
assert settings['showTurnDuration'] is True
|
|
195
|
-
for key in ['awaySummaryEnabled','autoMemoryEnabled','verbose','autoCompactEnabled','terminalProgressBarEnabled','useAutoModeDuringPlan']:
|
|
195
|
+
for key in ['awaySummaryEnabled','autoMemoryEnabled','verbose','autoCompactEnabled','terminalProgressBarEnabled','useAutoModeDuringPlan','enableWorkflows','workflowKeywordTriggerEnabled']:
|
|
196
196
|
assert key not in settings, key
|
|
197
197
|
allow=settings['permissions']['allow']
|
|
198
198
|
deny=settings['permissions']['deny']
|
|
@@ -319,7 +319,7 @@ STORE="$TMP/store"; export STORE; mkdir -p "$STORE"
|
|
|
319
319
|
valid_record "20260606T000000-aaaaaa" "native-a" > "$STORE/20260606T000000-aaaaaa.meta.json"
|
|
320
320
|
valid_record "20260606T000001-bbbbbb" "native-b" > "$STORE/20260606T000001-bbbbbb.meta.json"
|
|
321
321
|
|
|
322
|
-
STATUS_INPUT_MATCH='{"session_id":"native-a","workspace":{"current_dir":"/tmp"},"model":{"id":"claude-sonnet-
|
|
322
|
+
STATUS_INPUT_MATCH='{"session_id":"native-a","workspace":{"current_dir":"/tmp"},"model":{"id":"claude-sonnet-5"},"context_window":{"context_window_size":200000,"used_percentage":2,"current_usage":{"input_tokens":10}}}'
|
|
323
323
|
STATUS_INPUT_MISS='{"session_id":"native-missing","workspace":{"current_dir":"/tmp"},"model":{"id":"claude-opus-4-8"}}'
|
|
324
324
|
STATUS_INPUT_READY='{"workspace":{"current_dir":"/tmp"},"model":{"id":"claude-haiku-4-5"}}'
|
|
325
325
|
STATUS_OUT_MATCH="$(printf '%s' "$STATUS_INPUT_MATCH" | ENTWURF_META_SESSIONS_DIR="$STORE" "$REPO/scripts/meta-bridge-statusline.sh")"
|