@t2000/engine 1.13.1 → 1.15.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/dist/index.d.ts CHANGED
@@ -1715,41 +1715,50 @@ declare function bundleShortestTtl(toolUseIds: string[], toolNamesById: Record<s
1715
1715
  declare const REGENERATABLE_READ_TOOLS: ReadonlySet<string>;
1716
1716
 
1717
1717
  /**
1718
- * [Phase 0 / SPEC 13 / 2026-05-03] Maximum number of writes per atomic bundle.
1719
- *
1720
- * **History.** This was 5 between F14-fix-2 (2026-05-03 morning) and
1721
- * Phase 0 (2026-05-03 evening). The May 3 production review found that
1722
- * the underlying problem was never the count bundles fail because
1723
- * SDK appenders pre-fetch coins from the wallet and the chained asset
1724
- * doesn't exist there yet (e.g. `swap_execute(USDC→USDsui) +
1725
- * save_deposit(USDsui)` reverts at PREPARE because USDsui isn't in the
1726
- * wallet at compose time). SPEC 13 builds the chained-coin handoff
1727
- * primitive. Until that ships in `1.13.0`, Phase 0 strict-tightens
1728
- * bundles to:
1729
- *
1730
- * - Cap = 2 ops (was 5).
1731
- * - Every adjacent pair MUST be in `VALID_PAIRS` (was: any 2
1732
- * bundleable tools).
1733
- *
1734
- * **Why 2.** Every multi-write production failure today reduces to
1735
- * the same gap: a chained-asset bundle whose intermediate output
1736
- * doesn't exist in the wallet yet. The `VALID_PAIRS` whitelist below
1737
- * enumerates every (producer, consumer) couple where chaining either
1738
- * works today (because the consumer takes a wallet coin that the
1739
- * producer happens to leave there via `tx.transferObjects`) OR will
1740
- * work after Phase 1. Anything outside the whitelist falls through
1741
- * to sequential same outcome the LLM was already producing as a
1742
- * fallback, just without the wasted PREPARE round-trip.
1743
- *
1744
- * **Why not 3+.** 3-op chains require a graph validator (every adjacent
1745
- * pair valid + DAG topology checks) — that's Phase 2. Cap stays at 2
1746
- * until Phase 1 lands the validator.
1718
+ * [Phase 0 → Phase 3a / SPEC 13] Maximum number of writes per atomic bundle.
1719
+ *
1720
+ * **History.**
1721
+ * - Pre-Phase-0: 5 (F14-fix-2, 2026-05-03 morning).
1722
+ * - Phase 0 (1.12.0, 2026-05-03 evening): tightened to 2 after the May 3
1723
+ * production review found bundle failures all reduced to chained-asset
1724
+ * gaps the SDK pre-fetched coins from the wallet and the chained
1725
+ * asset didn't exist yet (e.g. `swap_execute(USDC→USDsui) +
1726
+ * save_deposit(USDsui)` reverted at PREPARE because USDsui wasn't in
1727
+ * the wallet at compose time).
1728
+ * - Phase 1 (1.13.0): cap stayed 2. SPEC 13 Phase 1 added the chained-
1729
+ * coin handoff primitive (`PendingActionStep.inputCoinFromStep` +
1730
+ * `composeTx` orchestration loop) but didn't widen the cap. The
1731
+ * primitive is what makes Phase 2's raise to 3 possible — without it,
1732
+ * every additional step is another wallet-fetch race.
1733
+ * - Phase 2 (1.14.0): cap raised to 3. Composition rule was strict-
1734
+ * adjacency: every (step[i], step[i+1]) pair must be in `VALID_PAIRS`.
1735
+ * Strict adjacency rejected DAG shapes (`swap save send` —
1736
+ * last pair `save→send` not in whitelist even though step 3 doesn't
1737
+ * chain from step 2; it pulls a fresh wallet coin).
1738
+ * - **Phase 3a (1.15.0, this version): cap raised to 4. Composition rule
1739
+ * relaxed to DAG-aware: only pairs that actually chain via
1740
+ * `inputCoinFromStep` need whitelist checking. Standalone steps
1741
+ * interleaved between chained steps run wallet-mode independently
1742
+ * inside the same atomic PTB.** This unlocks Demo 1 ("swap 10% to
1743
+ * SUI, save 50% as USDsui, send $100 to Mom" — 4-op DAG with one
1744
+ * chain at step 1→2, three standalone wallet-mode steps).
1745
+ *
1746
+ * **DAG-aware semantics.** Pre-3a: every adjacent pair gates the entire
1747
+ * bundle. Phase 3a+: each (i, i+1) pair contributes IF a chain is wired
1748
+ * (via `shouldChainCoin`). Non-chained pairs are independent — they
1749
+ * each pre-fetch their own coin from the wallet inside the PTB. Atomic
1750
+ * settlement at the PTB level holds either way.
1751
+ *
1752
+ * **Phase 3b (deferred):** `swap_execute → swap_execute` whitelist add
1753
+ * for explicit multi-hop swap chains (rare; flag-gated when shipped).
1754
+ * **Phase 5+:** cap > 4 once production telemetry confirms zero edge-
1755
+ * case revert rate at cap=4.
1747
1756
  *
1748
1757
  * Hosts importing this constant for system-prompt construction get the
1749
- * current cap automatically. Bumping the cap in Phase 1 + Phase 2 + …
1750
- * is a one-line change here that propagates to prompts via the import.
1758
+ * current cap automatically. Bumping the cap is a one-line change here
1759
+ * that propagates to prompts via the import.
1751
1760
  */
1752
- declare const MAX_BUNDLE_OPS = 2;
1761
+ declare const MAX_BUNDLE_OPS = 4;
1753
1762
  /**
1754
1763
  * [Phase 0 / SPEC 13] Whitelisted (producer, consumer) pairs for atomic
1755
1764
  * bundling. Every key has the shape `${producer}->${consumer}`. Bundles
package/dist/index.js CHANGED
@@ -6737,7 +6737,7 @@ var REGENERATABLE_READ_TOOLS = /* @__PURE__ */ new Set([
6737
6737
  ]);
6738
6738
 
6739
6739
  // src/compose-bundle.ts
6740
- var MAX_BUNDLE_OPS = 2;
6740
+ var MAX_BUNDLE_OPS = 4;
6741
6741
  var VALID_PAIRS = /* @__PURE__ */ new Set([
6742
6742
  "swap_execute->send_transfer",
6743
6743
  "swap_execute->save_deposit",
@@ -7885,7 +7885,7 @@ ${recipeCtx}`;
7885
7885
  }
7886
7886
  if (guardPassedWrites.length > MAX_BUNDLE_OPS) {
7887
7887
  const cappedError = {
7888
- error: `Atomic bundles are capped at ${MAX_BUNDLE_OPS} ops in Phase 0. You attempted ${guardPassedWrites.length}. Execute these as ${guardPassedWrites.length} sequential single-write transactions: tell the user "I'll do this in ${guardPassedWrites.length} steps", then emit only the FIRST write. After it lands and the user confirms each step, emit the next.`,
7888
+ error: `Atomic bundles are capped at ${MAX_BUNDLE_OPS} ops. You attempted ${guardPassedWrites.length}. Execute these as ${guardPassedWrites.length} sequential single-write transactions: tell the user "I'll do this in ${guardPassedWrites.length} steps", then emit only the FIRST write. After it lands and the user confirms each step, emit the next.`,
7889
7889
  _gate: "max_bundle_ops"
7890
7890
  };
7891
7891
  for (const write of guardPassedWrites) {
@@ -7916,41 +7916,6 @@ ${recipeCtx}`;
7916
7916
  const turnIndex = this.messages.filter((m) => m.role === "assistant").length;
7917
7917
  this.turnPaused = true;
7918
7918
  if (allBundleable) {
7919
- if (guardPassedWrites.length === 2) {
7920
- const producer = guardPassedWrites[0].call.name;
7921
- const consumer = guardPassedWrites[1].call.name;
7922
- const check = checkValidPair(producer, consumer);
7923
- if (!check.ok) {
7924
- const pairError = {
7925
- error: `Bundle pair '${check.pair}' is not in the Phase 0 chaining whitelist. Whitelisted pairs: ${[...VALID_PAIRS].join(", ")}. Run these two writes sequentially: tell the user "I'll do this in two steps", emit only the first write, then the second after it lands and confirms.`,
7926
- _gate: "pair_not_whitelisted"
7927
- };
7928
- for (const write of guardPassedWrites) {
7929
- yield {
7930
- type: "tool_result",
7931
- toolName: write.call.name,
7932
- toolUseId: write.call.id,
7933
- result: pairError,
7934
- isError: true
7935
- };
7936
- toolResultBlocks.push({
7937
- type: "tool_result",
7938
- toolUseId: write.call.id,
7939
- content: JSON.stringify(pairError),
7940
- isError: true
7941
- });
7942
- }
7943
- this.turnPaused = false;
7944
- this.messages.push({ role: "assistant", content: acc.assistantBlocks });
7945
- this.messages.push({ role: "user", content: toolResultBlocks });
7946
- getTelemetrySink().counter("engine.turn_outcome", {
7947
- entry: freshPrompt !== null ? "submit" : "resume",
7948
- outcome: "pair_not_whitelisted_continue",
7949
- pair: check.pair
7950
- });
7951
- continue;
7952
- }
7953
- }
7954
7919
  const completedResults = toolResultBlocks.map((b) => ({
7955
7920
  toolUseId: b.toolUseId,
7956
7921
  content: b.content,