@sema-ai/core 1.276.0 → 1.277.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 (147) hide show
  1. package/README.md +2 -5
  2. package/dist/bench/metrics.js +1 -1
  3. package/dist/bench/metrics.js.map +1 -1
  4. package/dist/core/auto-mode.d.ts.map +1 -1
  5. package/dist/core/auto-mode.js +14 -1
  6. package/dist/core/auto-mode.js.map +1 -1
  7. package/dist/core/cache-break-detector.js +0 -0
  8. package/dist/core/cache-break-detector.js.map +1 -1
  9. package/dist/core/task-registry.d.ts +6 -0
  10. package/dist/core/task-registry.d.ts.map +1 -1
  11. package/dist/core/task-registry.js +30 -0
  12. package/dist/core/task-registry.js.map +1 -1
  13. package/dist/tools/fs/index.d.ts.map +1 -1
  14. package/dist/tools/fs/index.js +5 -2
  15. package/dist/tools/fs/index.js.map +1 -1
  16. package/dist/tools/gitea-issue.d.ts +1 -1
  17. package/dist/tools/gitea-issue.d.ts.map +1 -1
  18. package/dist/tools/scheduler-tools.d.ts.map +1 -1
  19. package/dist/tools/scheduler-tools.js +8 -6
  20. package/dist/tools/scheduler-tools.js.map +1 -1
  21. package/package.json +3 -5
  22. package/CHANGELOG.md +0 -5444
  23. package/docs/A1-ATTRIBUTION-ROUND1-2026-07-09.md +0 -181
  24. package/docs/AB-ORACLE-GATE-VERDICT-2026-07-10.md +0 -100
  25. package/docs/ANCHOR-GAP-INVENTORY-2026-07-09.md +0 -143
  26. package/docs/ARCHITECTURE.md +0 -125
  27. package/docs/BUGHUNT-2026-07-05-NIGHT.md +0 -98
  28. package/docs/BUILD.md +0 -63
  29. package/docs/CANCEL-ASYNC-ATTRIBUTION-2026-07-09.md +0 -98
  30. package/docs/CC-198-VS-201-DRIFT-2026-07-09.md +0 -70
  31. package/docs/CC-BASELINE-FAKE-ZERO-AUDIT-2026-07-09.md +0 -51
  32. package/docs/CC-DRIFT-198-206-AGENT-TYPES-2026-07-10.md +0 -82
  33. package/docs/CC-DRIFT-198-206-CHANGELOG-2026-07-10.md +0 -82
  34. package/docs/CC-DRIFT-198-206-REMINDERS-2026-07-10.md +0 -96
  35. package/docs/CC-DRIFT-198-206-ROADMAP-2026-07-10.md +0 -110
  36. package/docs/CC-DRIFT-198-206-TOOL-INVENTORY-2026-07-10.md +0 -53
  37. package/docs/CC-DRIFT-198-206-USAGE-CONSTANTS-2026-07-10.md +0 -64
  38. package/docs/CC-DRIFT-198-206-WORKFLOW-2026-07-10.md +0 -83
  39. package/docs/CC-PARITY-CHECKLIST.md +0 -220
  40. package/docs/CC-PARITY-DEEP-SWEEP-2026-07-07.md +0 -149
  41. package/docs/CC-SUBAGENT-PROMPT-STUDY-2026-07-09.md +0 -219
  42. package/docs/CC-TASK-REMINDER-CADENCE-STUDY-2026-07-09.md +0 -396
  43. package/docs/CC-TOOL-PARITY-SWEEP-2026-07.md +0 -56
  44. package/docs/CC-TOOL-PROMPT-DEEP-DIFF-2026-07-08.md +0 -274
  45. package/docs/CC-TOOLSURFACE-DEEP-DIVE-2026-07-07.md +0 -197
  46. package/docs/CC206-OBSERVER-ANCHORS-2026-07-11.md +0 -463
  47. package/docs/CC207-CORE-SWEEP-BACKLOG-2026-07-12.md +0 -155
  48. package/docs/CENTER-CONTROL-PLANE-SEAM.md +0 -86
  49. package/docs/CLEANUP-CONTRACT-ANCHOR-2026-07-09.md +0 -83
  50. package/docs/COLD-START-RSI-2026-07-09.md +0 -72
  51. package/docs/COMPACTION-LIVE-AUDIT-2026-07-09.md +0 -114
  52. package/docs/CONTEXT-lifecycle-extension-points-and-stop-attribution.md +0 -71
  53. package/docs/COREWARS-POLYGLOT-TRIAGE-2026-07-09.md +0 -85
  54. package/docs/DEADTARGET-OVERFULL-HBOX-2026-07-10.md +0 -92
  55. package/docs/DEADTARGET-PATH-TRACING-REVERSE-2026-07-10.md +0 -87
  56. package/docs/DEADTARGET-WINNING-AVG-COREWARS-2026-07-10.md +0 -96
  57. package/docs/DEEPSEEK-API-LIMITS-PROBE-2026-07-09.md +0 -118
  58. package/docs/DESIGN-140-MOCK-VERIFY-2026-07-11.md +0 -79
  59. package/docs/DESIGN-140-VERIFICATION-2026-07-11.md +0 -43
  60. package/docs/DESIGN-DRAFT-workflow-collab-2026-07-11.md +0 -56
  61. package/docs/DESIGN-ORACLE-GROUNDING-GATE-2026-07-10.md +0 -167
  62. package/docs/DESIGN-TFRAG-RECONCILE-SCAFFOLD-2026-07-09.md +0 -102
  63. package/docs/EXP-PA2-PE-DESIGN-2026-07-11.md +0 -220
  64. package/docs/EXT-DOGFOOD-2026-07-12.md +0 -50
  65. package/docs/FINAL-VERIFY-SURFACE-AUDIT-2026-07-09.md +0 -44
  66. package/docs/FRAG-RECON-INVESTIGATION-2026-07-09.md +0 -183
  67. package/docs/HANDOFF.md +0 -121
  68. package/docs/KNOWN-ISSUES.md +0 -96
  69. package/docs/LEGW-WINDOW-TAX-2026-07-10.md +0 -82
  70. package/docs/LIVE-PROBE-BATCH-2026-07-11.md +0 -207
  71. package/docs/M2-CERT-ATTRIBUTION-2026-07-10.md +0 -61
  72. package/docs/M25-LEG-VARIANCE-ATTRIBUTION-2026-07-10.md +0 -81
  73. package/docs/MAILMAN-TIMEOUT-ATTRIBUTION-2026-07-10.md +0 -88
  74. package/docs/MEMORY-BACKEND-DIALECT-NOTES.md +0 -69
  75. package/docs/MTEB-ESCAPE-HATCH-ATTRIBUTION-2026-07-09.md +0 -57
  76. package/docs/MTEB-LEADERBOARD-ATTRIBUTION-2026-07-10.md +0 -134
  77. package/docs/ORACLE-GATE-NEGATIVE-SAMPLE-2026-07-11.md +0 -28
  78. package/docs/PARITY-CONTEXT-TRANSACTIONS-2026-07-10.md +0 -67
  79. package/docs/PARITY-PROGRESS-MATRIX-2026-07-10.md +0 -37
  80. package/docs/PARITY-SPOT-AGENT-TYPES-2026-07-10.md +0 -70
  81. package/docs/PARITY-SPOT-REMINDERS-2026-07-10.md +0 -144
  82. package/docs/PARITY-SPOT-TOOL-INVENTORY-2026-07-10.md +0 -61
  83. package/docs/PARITY-SPOT-USAGE-CONSTANTS-2026-07-10.md +0 -95
  84. package/docs/PARITY-SPOT-WORKFLOW-2026-07-10.md +0 -93
  85. package/docs/PASSWORD-RECOVERY-PANEL-VERDICT-2026-07-10.md +0 -62
  86. package/docs/R8-R9-FINALIZE-COORDINATION-2026-07-09.md +0 -124
  87. package/docs/REPL-CODE-MODE-EVALUATION-2026-07-10.md +0 -187
  88. package/docs/REPORT-1249-TARGETED.md +0 -48
  89. package/docs/RESEARCH-3P-MEMORY-SWAP-2026-07-12.md +0 -273
  90. package/docs/ROADMAP.md +0 -111
  91. package/docs/RSI-CLOUD-DEPLOY-2026-07-06.md +0 -289
  92. package/docs/RSI-PROCESS-AI-COLDSTART-2026-07-11.md +0 -68
  93. package/docs/S18-THOROUGHNESS-AUDIT-2026-07-09.md +0 -113
  94. package/docs/SERVICE-INTEGRATION-GUIDE.md +0 -298
  95. package/docs/SUBAGENT-STREAM-RESILIENCE-PARITY-2026-07-10.md +0 -118
  96. package/docs/SWEBENCH-PRO-RECON-2026-07-11.md +0 -31
  97. package/docs/TB-EFFICIENCY-TELEMETRY-2026-07-08.md +0 -114
  98. package/docs/TB-FAILURE-AUTOPSY-2026-07-05-RERUN.md +0 -67
  99. package/docs/TB-FAIRNESS-AUDIT-2026-07-08.md +0 -141
  100. package/docs/TB-FULL-1257-2026-07-08.md +0 -77
  101. package/docs/TB-LEG-GAP-ATTRIBUTION-1261-1263-2026-07-11.md +0 -154
  102. package/docs/TB-REGRESSION-DAEMON-KILL-2026-07-08.md +0 -58
  103. package/docs/TB-RSI-CROSSCHECK-2026-07-06.md +0 -68
  104. package/docs/TB-RSI-LEDGER.md +0 -30
  105. package/docs/TB-STABLE-SET-2026-07-08.md +0 -127
  106. package/docs/TB21-RECON-2026-07-11.md +0 -28
  107. package/docs/TEST-DESIGN-BATCH-1-2-3.md +0 -97
  108. package/docs/THIRD-PARTY-INTEGRATION.md +0 -45
  109. package/docs/TOKEN-ESTIMATE-CALIBRATION-LIVE-2026-07-09.md +0 -102
  110. package/docs/audit-2026-06-10-/347/254/254/344/272/214/350/275/256-/347/251/272/347/231/275/345/214/272/344/270/216/345/277/230/346/216/245/347/272/277.md +0 -147
  111. package/docs/audit-2026-06-10-/350/256/241/347/256/227bug/346/211/253/346/217/217.md +0 -163
  112. package/docs/audit-2026-06-11-/344/277/256/345/244/215/345/244/215/345/256/241/344/270/216/345/233/236/345/275/222/344/270/223/346/211/253.md +0 -95
  113. package/docs/audit-2026-06-12-design71-P1/346/275/234/344/274/217/351/235/242/350/243/201/345/206/263/344/270/216/345/220/236/351/224/231/345/256/241/350/256/241.md +0 -45
  114. package/docs/audit-2026-06-12-/345/205/254/345/274/200/346/227/213/351/222/256/346/264/273/346/200/247/344/270/216vendored/346/255/273/350/267/257.md +0 -63
  115. package/docs/audit-2026-06-15/ADDENDUM-second-pass.md +0 -88
  116. package/docs/audit-2026-06-15/ARCHITECTURE-AND-ROADMAP.md +0 -187
  117. package/docs/audit-2026-06-15/DOC-CORRECTIONS.md +0 -105
  118. package/docs/audit-2026-06-15/INDEX.md +0 -49
  119. package/docs/audit-2026-06-15/ORCHESTRATION-STATUS.md +0 -98
  120. package/docs/audit-2026-06-15/PRODUCTION-ISSUES.md +0 -189
  121. package/docs/audit-2026-06-15/REFERENCES-literature.md +0 -139
  122. package/docs/audit-2026-06-15/VENDOR-REFACTOR-PLAN.md +0 -96
  123. package/docs/cc-probe-198/README.md +0 -72
  124. package/docs/cc-probe-198/STABILITY-AUDIT.md +0 -118
  125. package/docs/cc-probe-198/live-schema-monitor-worktree-2026-07-09.json +0 -56
  126. package/docs/cc-probe-198/mount-variants.json +0 -536
  127. package/docs/cc-probe-198/plan-mode-run.json +0 -1
  128. package/docs/cc-probe-198/probe-bash-bg.json +0 -224
  129. package/docs/cc-probe-198/probe-edit-mismatch.json +0 -120
  130. package/docs/cc-probe-198/probe-read-missing.json +0 -62
  131. package/docs/cc-probe-198/probe-search-empty.json +0 -127
  132. package/docs/cc-probe-198/probe-task-family.json +0 -227
  133. package/docs/cc-probe-198/probes.status +0 -6
  134. package/docs/cc-probe-198/raw-capture-interactive.json +0 -948
  135. package/docs/cc-probe-198/raw-capture-print.json +0 -787
  136. package/docs/cc-probe-198/raw-capture2-interactive.json +0 -948
  137. package/docs/cc-probe-198/raw-capture2-print.json +0 -787
  138. package/docs/cc-probe-198/system-prompt.txt +0 -135
  139. package/docs/cc-probe-198/tools-array.json +0 -962
  140. package/docs/durability-boundary.md +0 -63
  141. package/docs/fix-2026-06-10-/350/256/241/347/256/227bug/344/277/256/345/244/215-search/346/211/271.md +0 -75
  142. package/docs/fix-2026-06-11-/347/254/254/344/272/214/350/275/256-/344/277/256/345/244/215-search/346/211/271.md +0 -62
  143. package/docs/parity-sweep/REPORT-DYNAMIC.md +0 -97
  144. package/docs/parity-sweep/REPORT-STATIC-GGB.md +0 -127
  145. package/docs/parity-sweep/REPORT-STATIC-RWE.md +0 -133
  146. package/docs/vendor-history.md +0 -385
  147. package/docs/vendored-upstream-diff-2026-07.md +0 -83
@@ -1,385 +0,0 @@
1
- # Vendored core — provenance & modifications
2
-
3
- Distilled from **openclaw** (https://github.com/openclaw/openclaw).
4
-
5
- - Baseline commit: `e3a6da0f51` (2026-06-12; advanced by the monthly diff review below)
6
- - Previous baseline: `2664f5951916f374907d693132f5315207f62fb6` (`2026.6.2`)
7
- - License: MIT (see openclaw/LICENSE)
8
-
9
- ## What was copied
10
-
11
- | vendor path | source in openclaw |
12
- |-------------|--------------------|
13
- | `src/vendor/llm-core/src/` | `packages/llm-core/src/` (full) — **since naturalized to `src/engine/llm/` (design/118 ①②, 2026-07-02)** |
14
- | `src/vendor/agent-core/src/` | `packages/agent-core/src/` (full) |
15
-
16
- ~~The two-package relative layout is preserved so agent-core's `../../llm-core/src/index.js` imports
17
- resolve against the vendored llm-core.~~ **Superseded (design/118 ①②)**: agent-core now imports the
18
- llm layer from the engine path (`../../../engine/llm/index.js`) — see the naturalized section below.
19
-
20
- ## Modifications applied
21
-
22
- 1. Deleted all `*.test.ts`.
23
- 2. Rewrote 3 package-name imports `@openclaw/llm-core` → relative
24
- `../../llm-core/src/index.js` (in `agent-core/src/{validation,agent-loop,llm}.ts`),
25
- since the workspace package is not published to npm. *(Superseded by design/118 ①②:
26
- these now point at `../../../engine/llm/index.js`.)*
27
- 3. **F2 optimistic-lock seam** (additive, backward-compatible — see `design/07`). Lets a durable
28
- `SessionStorage` make writes conditional so two instances waking the same session can't silently
29
- fork the tree. Touched 5 files:
30
- - `harness/types.ts` — `SessionErrorCode` += `"conflict"`; new `SessionWriteOptions`;
31
- `appendEntry`/`setLeafId` gain optional `opts?: SessionWriteOptions`.
32
- - `harness/session/storage-base.ts` — `protected assertExpectedLeaf(opts)`; abstract signatures
33
- accept `opts`.
34
- - `harness/session/memory-storage.ts` + `jsonl-storage.ts` — call `assertExpectedLeaf(opts)`
35
- before persisting. (`jsonl-storage.ts` since deleted — design/71 P0.)
36
- - `harness/session/session.ts` — `appendTypedEntry` passes `{ expectedLeafId: entry.parentId }`
37
- (the only site that threads it; intentional moves stay unconditional).
38
-
39
- 4. **F7 entry-id entropy** (`harness/session/storage-base.ts`). `generateEntryId` now slices the
40
- **random tail** of a uuidv7 (`slice(-8)`, the `rand_b` group) instead of the leading timestamp
41
- bytes (`slice(0,8)`), which only changed ~once per 65s and collided for every entry in a window.
42
- 5. **F3 branch-floor seam** (additive, backward-compatible). Lets a durable backend wake with only
43
- the bounded tail `[floorEntryId .. leaf]` instead of the whole tree.
44
- - `harness/session/storage-base.ts` — `BaseSessionStorage` constructor gains optional 4th arg
45
- `opts?: { floorEntryId? }`; `getPathToRoot` stops at the floor (its missing parent is expected,
46
- not an error); new `getFloorId()`. Unset floor = unchanged full-tree behavior.
47
- - `harness/session/memory-storage.ts` — `InMemorySessionStorage` options gain `floorEntryId`.
48
-
49
- 6. **`FileErrorCode` += `"timeout"`** (additive, backward-compatible — same shape as mod #3's
50
- `SessionErrorCode += "conflict"`). `harness/types.ts` only. Lets a **remote** `FileSystem` op surface a
51
- liveness/idle-timeout (a hung provider RPC) as a typed, retryable `FileError("timeout")` instead of
52
- `"unknown"`, symmetric with the core-owned `RemoteExecutionError` code `"timeout"`. For the
53
- service[45]/[49] remote-RPC-hang class-fix (`src/core/remote-env.ts` universal liveness contract). No
54
- behavior change — the base `NodeExecutionEnv`/`StubExecutionEnv` never emit it; only remote adapters do.
55
-
56
- 7. **Summarization-prompt anti-drift sections** (`harness/compaction/compaction.ts`, design/64 §22 /
57
- design/66 D / channel [73]). Added CC's anti-drift sections to `SUMMARIZATION_PROMPT` /
58
- `UPDATE_SUMMARIZATION_PROMPT` (verbatim "## User Messages", "## Errors & Fixes", Next-Steps guard,
59
- `<analysis>` scratch block stripped in core's `maybeCompact`). Prompt-only; no control-flow change.
60
-
61
- 8. **`turn_boundary` hook seam** (design/64 §25 (A), within-task compaction — additive,
62
- backward-compatible). The loop previously had no between-turn extension point, so LLM compaction
63
- could only run between tasks (`finish()`); within a task only the lossy trim floor applied.
64
- - `harness/types.ts` — new `TurnBoundaryEvent { type: "turn_boundary"; model }` in
65
- `AgentHarnessOwnEvent` + `AgentHarnessEventResultMap` (result `undefined` — pure timing signal).
66
- - `harness/agent-harness.ts` — `createLoopConfig.prepareNextTurn` emits it AFTER
67
- `flushPendingSessionWrites()` and BEFORE `createTurnState()`, so a handler that persists a
68
- session mutation (e.g. `session.appendCompaction`) is rebuilt into the very next request.
69
- Policy (thresholds, model, breaker) stays in core's runtask. No handlers ⇒ no behavior change.
70
-
71
- 9. **`ExecutionErrorCode` / `FileErrorCode` += `"transport_lost"`** (additive, backward-compatible —
72
- same shape as mod #6's `FileErrorCode += "timeout"`). `harness/types.ts` only. Lets a remote
73
- adapter (SSH channel death without exit-status, ADB device offline) surface a mid-session
74
- transport drop as a typed, retry-whitelist-visible error instead of `"unknown"` (service[63];
75
- the adapters previously had to encode it as a `[transport_lost]` message prefix). Exec outcome
76
- is UNKNOWN on this code — retry only per the op's idempotency, after reconnect.
77
-
78
- 10. **Compaction-estimate usage anchor follows usage SIGNAL, not stopReason**
79
- (`harness/compaction/compaction.ts` `getAssistantUsage`, design/64 §26.5 council #1). Was: skip
80
- `stopReason "error"|"aborted"`. Now: skip `"aborted"` and any assistant whose usage carries no
81
- signal (`calculateContextTokens(usage) === 0` — e.g. a synthetic loop-failure `EMPTY_USAGE`); an
82
- `"error"` assistant with REAL usage anchors. Closes both failure directions: error-only histories
83
- no longer fall back to the chars/4 heuristic for everything (≈2× underestimate on dense content ⇒
84
- missed compaction ⇒ provider truncation), and a zero-usage anchor can no longer swallow the whole
85
- prior history from the estimate.
86
-
87
- 11. **Compaction cut-point fallback + empty-preparation guards** (audit A-2 / design/64 §28.3;
88
- `harness/compaction/compaction.ts`). `findCutPoint`: when the keep budget is exhausted inside the
89
- trailing tool-result batch (no valid cut point at/after `i`), fall back to the LARGEST cut point
90
- ≤ `i` (was: the EARLIEST — which kept nearly everything, fed an empty conversation to the
91
- summarizer, and produced a hallucinated summary that GREW the context and shut within-task
92
- compaction down via the §25.2 floor). `prepareCompaction` returns `undefined` (quiet no-op) when
93
- nothing remains to summarize on a non-split cut; `compact()` errors loudly on an empty
94
- non-split preparation (defense-in-depth). Normal-path semantics unchanged.
95
-
96
- 12. **Interrupt leaves a legal session** (audit A-1 / design/64 §28.3; `agent-loop.ts`,
97
- `harness/agent-harness.ts`). (a) The inner loop checks the abort signal BEFORE streaming the next
98
- turn — an abort during a tool batch no longer triggers a doomed request whose synthetic empty
99
- `stopReason:"aborted"` assistant landed in the session between the interrupted batch and its
100
- reconcile tool_results (a permanently API-invalid sequence on strict providers). (b)
101
- `handleAgentEvent` skips PERSISTING empty failure assistants (aborted/error with no
102
- text/thinking/toolCall content — not model output); they still flow to live subscribers and the
103
- prompt() result. Callers signal interrupts via the run-loop's own abort flag (core
104
- `ResultFlags.abortedLive`), not the now-absent synthetic message.
105
-
106
- 13. **Signal-terminated exec is not exit 0** (audit round-2 A-3; `harness/env/nodejs.ts`). The
107
- `close` handler now receives `(code, signal)`: a signal-killed child (OOM SIGKILL, SIGSEGV,
108
- external kill) reports the conventional `128 + signum` exit code (best-effort 137 for unknown
109
- names) with a `[process terminated by <SIG>]` stderr marker, instead of `code ?? 0` = a fake
110
- success with half an output that the model advanced on.
111
-
112
- 14. **Full-output capture race** (audit round-2 A-4; `harness/utils/shell-output.ts`). ⚠️ FILE DELETED
113
- (design/118 ⓪, 2026-07-02): `shell-output.ts` + `truncate.ts` were runtime-dead (zero src consumers —
114
- the Bash tool and the engine `NodeExecutionEnv` own their own capture/truncation; zero downstream
115
- npm-dist consumers — the package `exports` map pins `.` + `./bench` only and none of the symbols are
116
- re-exported from `src/index.ts`). The A-4 edit is preserved here as history; its tests went with the file.
117
- `fullOutputRequested` flips SYNCHRONOUSLY on the first over-threshold chunk (was gated on
118
- `fullOutputPath`, assigned only inside the queued creation task — two fast chunks could create a
119
- second temp file that overwrote the path: in-between chunks landed in the orphaned file while the
120
- model was pointed at the new one = silent data loss). Appends now resolve the path INSIDE the
121
- queued task, so writes queued during creation land in the single created file.
122
-
123
- 15. **`ExecutionEnv.readLink` (optional, additive/backward-compatible)** (design/72 §2.1;
124
- `harness/types.ts` interface + `harness/env/nodejs.ts` impl). One-hop symlink target read (raw,
125
- not followed). Lets the canonical resolver follow a DANGLING leaf symlink — one whose target
126
- doesn't exist yet, which `canonicalPath`'s `realpath` cannot resolve — so a sensitive-path guard
127
- or rootPath containment sees the real target of `write_file innocent.txt` where
128
- `innocent.txt -> .git/hooks/payload`. Optional: a remote env that omits it keeps the prior
129
- best-effort behavior (canonicalize to the raw path). `NodeExecutionEnv` implements it.
130
-
131
- 16. **Wire the existing `shouldStopAfterTurn` callback** (design/74 R3-A; `harness/agent-harness.ts`).
132
- The loop already defines a clean-exit callback (`agent-loop.ts`: `if (await config.shouldStopAfterTurn?.(…))
133
- { emit agent_end; return }`) but `createLoopConfig` never provided it. Added a one-way `_stopAfterTurn`
134
- flag + a public `requestStopAfterTurn()` setter + wired `shouldStopAfterTurn: () => this._stopAfterTurn`.
135
- Lets the runner's resource-slice suspend (design/74) stop the loop CLEANLY at the turn boundary
136
- (`agent_end` + return) instead of via `abort()` — a hard abort with no `suspendRef` would drive the
137
- orphan-[INTERRUPTED] session reconcile and corrupt the resumed state. Additive + opt-in (flag defaults
138
- `false` → zero behavior change for any run that never calls `requestStopAfterTurn`).
139
- Council design/74 #1: the flag is reset to `false` at the top of `prompt()` so the stop is ONE-SHOT per
140
- prompt — a re-prompt/reuse of the harness can't inherit a stale stop and silently end after one turn.
141
-
142
- 17. **Null-coercion fail-open closed** (`llm-core/src/validation.ts`, CC-parity bug-hunt A1; ⚠️ this file
143
- was previously BYTE-IDENTICAL to openclaw — this is the first divergence). `coercePrimitiveByType`
144
- fabricated `null → 0/0/false/""` for plain JSON-schema (non-TypeBox) params. That is library-grade
145
- leniency; in our autonomous/GATED/MCP executor it is a FAIL-OPEN — a model emitting explicit `null` on a
146
- required non-nullable scalar (a deliberate decline) of a side-effecting/MCP tool was silently rewritten to
147
- a concrete `0` and executed, hidden from the design/37 policy gate. The four `value === null` fabricate
148
- rules were removed so `null` falls through to `return value` → `validator.Check` rejects → surfaced as a
149
- malformed tool call. Reachable only when null is NOT a valid union member (nullable schemas short-circuit
150
- before this branch via `matchesUnionMember`), so benign `"5"→5` leniency is untouched. (Directly analogous
151
- to the D1 env-scrub adjudication: openclaw's library defaults carry a changed meaning in our threat model.)
152
- 18. **Compaction "preserved verbatim" anchor** (`agent-core/src/harness/messages.ts`, CC-parity bug-hunt B4).
153
- Appended CC's `Recent messages are preserved verbatim below.` to `COMPACTION_SUMMARY_SUFFIX`. openclaw
154
- has the identical neutral wrapper with no anchor; our engine ALWAYS retains the `keepRecentTokens` recent
155
- tail after the summary, so (unconditionally, mirroring CC `services/compact/prompt.ts`) the model is told
156
- the post-summary messages are the real recent context, not re-summarized — avoids redundant re-acknowledgment.
157
-
158
- 19. **D1 secret-env protection NATURALIZED to first-party** (`harness/env/nodejs.ts` → imports
159
- `src/core/secret-env.ts`). The D1 shell-env scrubber (`scrubSecretEnv` + the secret-key pattern) was OUR
160
- security invariant, not openclaw — it was extracted to the first-party `src/core/secret-env.ts` (the
161
- canonical, vendor-independent home) so (a) the package's public exports `isSecretEnvKey`/`scrubSecretEnv`
162
- point at a STABLE path that survives the planned de-vendoring, and (b) a downstream host/exec adapter
163
- (service [265]) reuses the SAME pattern with zero drift. ⚠️ This is the FIRST vendored→first-party import,
164
- so the vendored tree no longer typechecks fully standalone — an intentional naturalize step (the D1 logic
165
- is first-party; this temporary vendored env merely consumes it ahead of NodeExecutionEnv's de-vendoring).
166
- 20. **D2 exec output-tail bound NATURALIZED to first-party** (`harness/env/nodejs.ts` → imports
167
- `src/core/exec-output-tail.ts`). Same rationale as #19: the D2 rolling-tail output bound (`RollingTailBuffer`
168
- + `MAX_EXEC_OUTPUT_BYTES` + the model-facing `markTruncated`) is OUR robustness invariant, extracted to the
169
- first-party `src/core/exec-output-tail.ts` so the public exports survive de-vendoring and a downstream exec
170
- adapter (service [267], 5 adapters with the same OOM vector) reuses ONE implementation + ONE marker. The
171
- vendored env now consumes it (string chunks for the onStdout/onStderr callbacks are pushed as Buffers; the
172
- bound is now byte-precise vs the old char-count — a strict improvement for OOM protection).
173
-
174
- 21. **Session type-only coupling REMOVED via dependency inversion** (`harness/types.ts`). The vendored harness
175
- used to `import type { Session }` from the first-party `engine/session/session.ts` (a concrete class) and
176
- re-export it — a vendored→first-party TYPE coupling. Replaced with a vendored-local `interface SessionApi`
177
- (the session CONTRACT the harness consumes); the first-party `class Session implements SessionApi`. The
178
- substrate now defines the interface it needs and never reaches into first-party for a session type. Named
179
- `SessionApi` (not `Session`) so it coexists with the public, constructable `class Session` — no breaking
180
- public-API change (the public `Session` stays a class; `SessionApi` is an additive export). Consumers that
181
- receive a session from a `SessionRepo`/`SessionStore` (session-store, memory-repo, `AcquiredSession`) now
182
- type it as `SessionApi`; only `new Session` sites use the concrete class.
183
- 22. **Residual null-fabrication fail-open closed** (`llm-core/src/validation.ts`, R3 adversarial bug-hunt).
184
- The A1 edit (#17) dropped the `null→scalar` coercion rules but left the REVERSE `case "null"`:
185
- `"" | 0 | false → null`. For a null-FIRST nullable union (`type:["null","string"]`) the coercion loop
186
- tries `"null"` first, so a model sending a concrete falsy scalar (0/false/"") had it silently fabricated
187
- into `null` and executed past the design/37 gate (reachable via a plain-JSON-schema MCP tool). Now
188
- `case "null"` returns the value unchanged — only a literal `null` satisfies a null type, symmetric with
189
- #17's closed direction.
190
-
191
- 23. **`message_end` carries its committed `entryId`** (message-identity Phase 1; `agent-core/src/types.ts`,
192
- `agent-core/src/harness/agent-harness.ts`). Additive optional `entryId?: string` on the `message_end`
193
- `AgentEvent`. `handleAgentEvent` KEEPS the id `session.appendMessage` already RETURNS (`session.ts:168`)
194
- instead of discarding it, and threads it onto the emitted event via a fresh `{ ...event, entryId }` (never
195
- mutates `event`). Captured **synchronously at the append site** — NOT a post-hoc `getLeafId()` read (which
196
- races the continuing loop). The empty-failure-assistant skip (`agent-harness.ts:601`) appends nothing ⇒
197
- `entryId` undefined ⇒ the event is emitted as-is and first-party publishes no `message_committed`. First-party
198
- (`runtask.ts` `onMessageEnd`) re-publishes it as the `message_committed` wire event for the renderable roles
199
- `message_end` carries (user/assistant/toolResult — see `types.ts:486`); resume tool-results are first-party
200
- -owned and need no vendored edit. Additive, optional; no reader outside core ⇒ zero behavior change. TRIPWIRE
201
- for an upstream re-apply = `test/streaming.test.ts` "message-identity Phase 1" — it cross-checks each wire
202
- `entryId` against the real session entry AND asserts EXACTLY one commit per persisted message (so a broken
203
- capture → undefined `entryId` → missing commits → RED; the empty-failure skip → no phantom commit by count).
204
- *Considered + rejected:* a first-party `onEntryCommitted` sink at `engine/session/session.ts` (covers all
205
- append kinds in one place, zero vendored edit) — reserved as the Phase-2 escape hatch for non-message floor
206
- types; it over-emits for non-rendered appends and couples the reusable `Session` to run-loop wire bookkeeping.
207
-
208
- 24. **Tool aliases for CC canonical-name convergence** (design/115 P0; `llm-core/src/types.ts`,
209
- `llm-core/src/validation.ts`, `agent-core/src/types.ts`, `agent-core/src/validation.ts`, `agent-core/src/agent-loop.ts`).
210
- Additive optional `Tool.aliases?: string[]` / `AgentTool.aliases?: string[]`, plus a shared `findToolByName`
211
- resolver that tries the canonical name first and then aliases. The live loop now uses it both for validation/
212
- preparation and for the sequential-batch pre-scan, so a legacy model/SDK call like `Task` or `KillShell`
213
- dispatches to the canonical `Agent`/`TaskStop` tool without bypassing per-tool execution mode. This is an
214
- engine compatibility shim for durable transcripts and old clients; new tool rosters still expose canonical
215
- names.
216
-
217
- Vendored core typechecks standalone with ZERO vendored→first-party imports (verified 2026-07-02,
218
- design/118 ⓪): `harness/env/nodejs.ts` — the former home of the D1/D2 naturalization imports (#19/#20)
219
- and the A-3 signal fix (#13) and readLink (#15) — was itself naturalized into
220
- `src/engine/execution-env/node-execution-env.ts`, taking those couplings with it. The vendored tree's
221
- only external dependency is `typebox`. The Session TYPE coupling (#21) is gone. (Reconcile / F1 in 1.2.0
222
- was pure `src/core/` — no vendor edit.)
223
-
224
- ## Deleted dead code (design/71 P0, 2026-06-12)
225
-
226
- Zero-consumer files (verified by symbol-level grep over `src/` + `test/`, barrel narrowed in the
227
- same commit; retreat path = git history, one commit per deletion):
228
-
229
- | deleted | LOC | why dead here |
230
- |---|---|---|
231
- | `agent-core/src/agent.ts` | 611 | upstream high-level `Agent` API; our entry is `Runner` → `harness.prompt` |
232
- | `agent-core/src/harness/session/jsonl-{storage,repo}.ts` | 450 | on-disk sessions; we use in-memory + first-party PG storage (both derive `BaseSessionStorage`) |
233
- | `agent-core/src/harness/compaction/branch-summarization.ts` + `AgentHarness.navigateTree()` | 323+137 | upstream interactive branch navigation/summary; zero callers, unreachable from `Runner` → `harness.prompt`. Historical `branch_summary` entries still read/replay fine (`session.moveTo` + compaction handle the entry type) |
234
- | `agent-core/src/harness/system-prompt.ts` | 39 | we build system prompts in the core-layer roles system |
235
- | `agent-core/src/node.ts` | 2 | upstream entry remnant (`NodeExecutionEnv` is re-exported via `src/internal/harness.ts` deep path) |
236
-
237
- Types referenced only by deleted code (`Jsonl*`, `NavigateTreeResult`, `BranchSummaryError`,
238
- `session_before_tree` hook shape) stay in `harness/types.ts` for now — design/71 P1 adjudicates them.
239
-
240
- ## Deleted dead code (design/118 ⓪ de-vendoring pre-clean, 2026-07-02)
241
-
242
- | deleted | LOC | why dead here |
243
- |---|---|---|
244
- | `harness/utils/truncate.ts` | 370 | zero src consumers (only `shell-output.ts` imported it); first-party tools own their truncation (`core/tool-errors.ts`, `core/exec-output-tail.ts`) |
245
- | `harness/utils/shell-output.ts` | 202 | zero runtime consumers (`executeShellWithCapture` unused by the Bash tool / any src path); downstream npm-dist consumption impossible (package `exports` = `.` + `./bench` only; symbols never re-exported from `src/index.ts`; downstream repos grep-verified zero imports, installed `node_modules/@sema-ai/core` 1.208/1.209 exports maps confirm) |
246
-
247
- The only in-repo consumers were the A-4 describes in `test/exec-shell.test.ts` (tests of the dead code) —
248
- removed with the files. Mod #14 above records the A-4 edit as history. Retreat path = git history.
249
-
250
- ## Naturalized out of this tree (design/71 P2 — ownership transferred to src/engine)
251
-
252
- - `harness/compaction/{compaction,utils}.ts` → `src/engine/compaction/` (2026-06-13). First-party
253
- ownership: no VENDORED EDIT discipline, direct unit tests, no upstream sync promise (upstream
254
- compaction diffs become reference reading). The vendored `agent-harness.ts` now imports the
255
- compaction entry points from the engine path (one import-line diff vs upstream). Boundary table:
256
- `src/engine/README.md`.
257
- - `harness/session/{session,storage-base,memory-storage,memory-repo,repo-utils,uuid}.ts` →
258
- `src/engine/session/` (2026-06-13, P2-②). Same terms. `harness/session/timestamps.ts` stayed
259
- vendor at the time (since moved — design/118 ③, see below); `harness/types.ts` imports the `Session` type from the engine
260
- path (one import-line diff vs upstream). design/71 hot path now fully naturalized.
261
- - `harness/env/nodejs.ts` → `src/engine/execution-env/node-execution-env.ts` (design/103). Carries
262
- mods #13 (signal exit), #15 (readLink), #19/#20 (D1/D2 first-party imports) with it — those mods'
263
- `harness/env/nodejs.ts` references now mean the engine file. `harness/env/kill-tree.ts` stayed vendor
264
- at the time (moved by de-vendoring unit ③ — see below).
265
- - **the agent loop itself** → `src/engine/loop/{agent-loop,types,runtime-deps}.ts` (2026-07-02,
266
- design/118 ④a de-vendoring). agent-loop.ts is a REWRITE, not a move: the vendored nested
267
- while-loops became an explicit state machine (named `LoopTerminal`/`LoopContinue` transitions,
268
- assertable via a trace sink — `test/loop-transitions.test.ts`), behavior-1:1 with the vendored
269
- loop. Carries mod #12(a) (A-1 abort-before-stream), the durable double-execution gate
270
- (design/45 §4.ter), the D4 post-hook posture, #24 alias dispatch, and the C9 partial-less delta
271
- reconstruction with it — each pinned red→green by counterfactual. The dual steer/followUp drain
272
- points are now named Continue reasons (`steer_injected`/`follow_up_injected`) with a direct
273
- dual-drain contract test. types.ts/runtime-deps.ts moved near-verbatim (mod #23
274
- `message_end.entryId`, `AgentTool.aliases`). Live-verified (tool/multi-turn + steering/interrupt
275
- 4/4 on the real gateway). ④b recovery chains build on this skeleton.
276
- - **harness contract layer** → `src/engine/harness/{types,messages}.ts`,
277
- `harness/env/kill-tree.ts` → `src/engine/execution-env/kill-tree.ts`,
278
- `harness/session/timestamps.ts` → `src/engine/session/timestamps.ts` (2026-07-02, design/118 ③
279
- de-vendoring). Carries mods #3 (F2 types), #6/#9 (timeout/transport_lost error codes), #8
280
- (turn_boundary event/result-map), #15's interface half (readLink), #18 (B4 compaction anchor),
281
- #21 (SessionApi inversion), and the design/116 detach seam (`detachSignal`/`detached`) with it —
282
- those mods' `harness/types.ts`/`harness/messages.ts` references now mean the engine files. The
283
- vendored `agent-harness.ts` imports the contract layer from the engine path; the agent-core barrel
284
- re-exports it so the facade surface is unchanged. After ③ the vendor tree = agent-loop.ts +
285
- agent-harness.ts + types.ts + runtime-deps.ts + barrels (units ④⑤ retire it).
286
- - **`llm-core` (ALL of it)** → `src/engine/llm/{types,diagnostics,event-stream,validation}.ts`
287
- (2026-07-02, design/118 ①② de-vendoring). Carries mods #17/#22 (validation fail-open closures),
288
- #24 (Tool.aliases + `findToolByName`), the C9 `text_delta.partial` cherry-pick, and the
289
- design/71 `end()` deadlock fix with it. The vendored agent-core now imports the llm layer from
290
- the engine path (`../../../engine/llm/index.js`, 8 import-line diffs vs upstream — same
291
- transitional pattern as compaction/session; these vanish when units ④⑤ retire the tree). The
292
- "zero vendored→first-party imports" note below predates this and is superseded accordingly.
293
-
294
- ## Latent surface adjudicated (design/71 P1, 2026-06-12)
295
-
296
- The "present but unused" C-class surface is now resolved — full record (per-file verdicts + the
297
- error-path audit) in `docs/audit-2026-06-12-design71-P1潜伏面裁决与吞错审计.md`:
298
-
299
- - **Deleted**: `prompt-templates.ts` + `prompt-template-arguments.ts` + `file-loader-utils.ts` +
300
- `skills.ts` (766 LOC) and the zero-caller `AgentHarness.skill()`/`promptFromTemplate()` methods
301
- (VENDORED EDIT markers in `agent-harness.ts`); npm deps `ignore`/`yaml` dropped with them.
302
- Deeper than the original plan: `formatSkillInvocation`'s only caller was itself uncalled, so the
303
- WHOLE skills surface was dead — which exposed `TaskSpec.skills` as a silently-inert public API
304
- (black-box instance #5; the field is kept with an honest ⚠️INERT JSDoc until its disposition is
305
- decided).
306
- - **Kept (type-level only)**: `Skill` (used by core `toSkill`), `PromptTemplate`, `Jsonl*`,
307
- `NavigateTreeResult`, `BranchSummaryError`, `session_before_tree` — removing them means
308
- refactoring the `AgentHarness<TSkill,TPromptTemplate,TTool>` generic threading = a big cold-path
309
- diff against upstream. Swept per-file during P2 naturalization instead.
310
-
311
- (`env/nodejs.ts` + `kill-tree.ts` are NOT unused — `NodeExecutionEnv` is the default hands
312
- execution env since design/44.)
313
-
314
- ### 2026-06-25 bug-hunt adjudications (round-5 deferred items)
315
-
316
- - **#10 — Deleted `AgentHarness.compact()`** (`agent-harness.ts`, with its 3 first-party imports
317
- `compact`/`prepareCompaction`/`DEFAULT_COMPACTION_SETTINGS`). Zero callers (within-task compaction goes
318
- through the first-party `maybeCompact` turn-end seam), `AgentHarness` not exported, AND it skipped the
319
- first-party `<analysis>`-strip + empty-summary guard — an unreachable divergence landmine. Same precedent as
320
- `navigateTree`/`skill` above; deleting it also removed a vendored→first-party import.
321
- - **#5 — `pendingSessionWrites` flush vs `reconcileInterruptedSession` ordering: adjudicated UNREACHABLE,
322
- fix deferred to de-vendoring.** A caller-queued non-toolResult write (`appendMessage`/`setModel`) flushed
323
- during a mid-batch abort could land between an open `tool_call` and its synthetic reconcile result =
324
- invalid transcript for strict providers. But it is unreachable in this package: `AgentHarness` is not
325
- exported (no external library consumer can queue mid-batch), and the engine's ONLY mid-task queuer
326
- (`setModel` at `runtask.ts` onTurnEnd) is a clean turn boundary with no open batch. A real fix would
327
- entangle the harness flush with the first-party reconcile ordering (risk for zero current benefit), so it
328
- is deferred to the harness de-vendoring/refactor rather than patched in soon-to-move vendored code.
329
-
330
- ## Monthly upstream diff review (design/71 §2.6 routine)
331
-
332
- | date | upstream range | commits | verdicts (要/不要/已有) | notes |
333
- |---|---|---|---|---|
334
- | 2026-06-13 | `2664f595..e3a6da0f51` | 13 touching the two packages | **1 要 / 9 不要 / 0 已有** (+3 out-of-scope) | first run; details below |
335
- | 2026-06-20 | `e3a6da0f51..d72f7edf2d` | 3 touching the two packages | **0 要 / 3 不要** (+2179 out-of-scope) | all 3 diverged; details below |
336
-
337
- ### 2026-06-13 adjudication detail (cold path only; hot path = engine, reference reading)
338
- - **要 → cherry-picked `6fcc945702`** (trim dense text-delta snapshots): `text_delta.partial` is now
339
- optional + the loop reconstructs partial-less deltas (`resolveAssistantMessageUpdate`). For us:
340
- zero behavior change today (our brains always send `partial`), but it removes a transient
341
- `context.messages` corruption window if a brain ever omits it, enables the snapshot-per-token
342
- memory trim brain-side later, and keeps the type contract upstream-aligned. Pinned by
343
- vendor-contracts C9 (e2e; see its honesty note on discrimination).
344
- - **不要 `0e7b5c3429`** (Claude Fable 5 adaptive thinking, + new `reasoning.ts`/`model-contracts/anthropic.ts`):
345
- upstream solves it in their provider-contract layer, which we deliberately replaced with the
346
- design/46 brain-compat system — equivalent handling belongs in `src/brain/anthropic.ts` compat
347
- if/when Fable 5 runs through it (flagged as a design/46 follow-up), not in the vendored loop.
348
- - **不要 `f80f472190`** (`AssistantMessage.errorCode/errorType/errorBody`): our error classification
349
- is the `[code]` prefix → `TaskResult.errorCode` pipeline; adding three reader-less optional fields
350
- violates the #5 liveness discipline (a brain author setting `errorCode` would be silently
351
- ignored). If we migrate to structured error fields, do it WITH the readers as a design item.
352
- - **不要 `1824aa07a0`/`72bfc5e9bf`** (`Model.supportsPromptCacheKey`/`authHeader`): consumed by their
353
- provider layer only; our brains own auth/cache behavior. Reader-less flags here = #5-shaped.
354
- - **不要 `b4dfa950b5`** (rename `AgentHarness`→`CoreAgentHarness` + re-export, surface refactor):
355
- cosmetic; our harness has deliberately diverged (deleted navigateTree/skill etc.) — churn for
356
- diff aesthetics only.
357
- - **不要 `81234fbf12`** (Skill `promptVersion`): skills are first-party now (design/71 #5 fix);
358
- noted as a possible future addition to OUR skills block, not a vendor sync.
359
- - **不要 docs×3** (`4df95d3c3f`/`bdfeece562`/`0b8aabe864`): header-comment passes (+1 line per file).
360
- - **Out of scope**: `462092936a` (their app layer `src/agents/`, not the vendored packages);
361
- hot-path/deleted-file changes (compaction/session/skills/agent.ts upstream diffs = reference only).
362
-
363
- ### 2026-06-20 adjudication detail (`e3a6da0f51..d72f7edf2d`; 3 commits touch the two vendored packages — all 不要)
364
- - **不要 `1a002c2d9d`** (preserve prompt-released session state, #93193): targets upstream **side-append (`appendMode:"side"`) + JSONL transcripts + transcript-navigation + doctor-repair** concurrency — all DELETED here (jsonl-storage + navigateTree, design/71 P0) or never present (no side-append concept). Our session concurrency is the F2 optimistic-lock CAS (design/07, `expectedLeafId`), a different model; the leaf-chain append has no side-append/stale-manager/navigation interaction to fix.
365
- - **不要 `0314819f91`** (replace prose terminal classifiers → `executionStarted` boolean): an agent-loop-INTERNAL terminal/tool classifier field. Our terminal + error classification is in the CORE layer (`runtask.ts` `errorCodeOf`/`isError` + the design/37 tool gate + the `[code]`-prefix → `TaskResult.errorCode` pipeline). Adding `executionStarted` to the vendored loop with no core reader = #5-shaped reader-less flag (same rejection class as 2026-06-13's `f80f472190`/`1824aa07a0`). Structured per-tool execution provenance, if wanted, is a core design item WITH a reader — not a vendor sync.
366
- - **不要 `965fa05df3`** (tool search directory mode → `resolveDeferredTool` agent-loop callback): we already have the equivalent via **design/36** (`deferMode:"auto"` + an injected `tool_search` driving `setTools`/rematerialize — types.ts:1150 / prepare-task.ts:592), a DIFFERENT mechanism needing no run-loop change. Upstream's `resolveDeferredTool` is a loop callback (changes the vendored loop); ours stays out of the loop. No sync.
367
- - **Out of scope**: 2179 commits not touching `packages/{llm-core,agent-core}/src`, or touching our naturalized hot path (compaction/session = engine path, reference reading) or deleted files (jsonl/agent.ts/navigateTree).
368
- - **baseline NOT advanced** (0 cherry-pick → vendored code unchanged, still `e3a6da0f51` + the mods above). Next monthly diff starts from `d72f7edf2d` (this review's HEAD). The 3 rejections confirm the deliberate divergence holding: deleted dead code, naturalized hot path, and different concurrency/tool/error-classification designs mean upstream's cold-path churn keeps not applying.
369
-
370
- ## Updating from upstream
371
-
372
- Re-copy the two `src/` dirs from a newer openclaw checkout, re-apply the modifications above,
373
- re-run `npm run typecheck`. Record the new baseline commit here.
374
-
375
- ---
376
-
377
- ## RETIRED (design/118 ⓪-⑤, 2026-07-02)
378
-
379
- `src/vendor/` no longer exists. The whole tree was de-vendored into first-party code — see the
380
- "Naturalized out of this tree" entries above for the per-unit map (llm → `src/engine/llm/`,
381
- harness contract + AgentHarness → `src/engine/harness/`, loop → `src/engine/loop/`, kill-tree →
382
- `src/engine/execution-env/`, timestamps → `src/engine/session/`). This file is preserved as the
383
- provenance/modification HISTORY of the vendored era (openclaw distillation, mods #1-#24, the
384
- monthly upstream-diff routine — now terminated). Behavior pins live in the test suite
385
- (vendor-contracts C1-C10, loop-transitions, streaming TRIPWIRE), not in an upstream diff.
@@ -1,83 +0,0 @@
1
- # 月度上游 diff 例行 — 2026-07(design/71 例行,design/118 后首次)
2
-
3
- - **上游**:openclaw(https://github.com/openclaw/openclaw),本地 checkout `/Users/clay/开发/gittea/openclaw`,fetch 成功。
4
- - **Baseline(上月)**:`e3a6da0f51`(2026-06-12)
5
- - **新 HEAD(本月)**:`53d0c4ca50` origin/main(2026-07-07)
6
- - **区间总提交**:6514;**命中原 vendored 来源目录**(`packages/agent-core` + `packages/llm-core`,见旧 VENDOR.md 出处表):**31 条**。
7
- - 背景:design/118 后 `src/vendor/` 不复存在,推理循环/compaction/session 已 first-party 化(`src/engine/`)。本例行仍以这两个上游目录为参照面逐条判决。
8
-
9
- ## 判决表(31 条,按主题聚类)
10
-
11
- 档位:**PORT** = 值得吸收(逐条给了落点);**KEEP** = 我们 first-party 实现已覆盖同类(含更强形态);**IGNORE** = 形状不存在于我们代码/纯上游内务。
12
-
13
- ### A. 压缩(compaction)— 5 条
14
-
15
- | 上游提交 | 内容 | 判决 | 依据(我们侧) |
16
- |---|---|---|---|
17
- | `2ece2945ae` | cut-point 估算器不数 user 消息里的 image 块 → 图重会话压缩 no-op 循环 | **PORT ①** | **同类 bug 在我们代码坐实**:`src/engine/compaction/compaction.ts` `estimateTokens` user 分支(~L314-327)只数 `text` 块,image 块记 0;toolResult 分支已有 `IMAGE_TOKEN_ESTIMATE`(design/123 D2)。修法:user 分支复用同一 image 计权(以及 document/PDF 计权对称)。危害比上游轻(A-2 修已挡住 no-op 灾难形态),但估算不对称仍在。 |
18
- | `f826a665a2` | 结尾超大 toolResult 时 findCutPoint 卡在 keep-everything → 压缩 no-op | KEEP | 我们早于上游修过同类:audit A-2 / design/64 §28.3(`findCutPoint` fallback = 最大的 ≤i cut point,L500-517),覆盖同一失效类。 |
19
- | `413acc2e63` | 数嵌套 toolResult 块内容(content 数组里出现 `toolResult` 型块) | IGNORE | 我们 `ToolResultMessage.content` 类型 = `(Text\|Image\|Document)[]`(`src/engine/llm/types.ts:368-376`),嵌套 toolResult 块形状不存在。 |
20
- | `e6ec74c254` | `calculateContextTokens` 优先用 provider 的 `usage.contextUsage`(available/unavailable 态) | IGNORE(WATCH) | 依赖 openclaw `packages/ai` 新 Usage 形状(Anthropic context-tracking 字段),我们 brains 的 Usage 没有该字段;现行 `totalTokens \|\| 各项和` 已含 cacheRead/cacheWrite。若日后 brains 接 Anthropic context_management,再回看。 |
21
- | `486033b183` | 压缩失败/超时恢复不再留下 assistant-last 卡死尾;typed 错误码,不触发 model-fallback 降级 | KEEP | 架构不同:我们压缩失败=抛出→调用方计入 §17.4 breaker(`src/core/auto-compaction.ts:264-266`),1.214 已做 errorKind 契约+length-recovery;无「恢复 pre-compaction 状态」路径,assistant-last 有 loop 侧防卫(agent-loop L218/286)。 |
22
-
23
- ### B. 推理循环(agent-loop)— 4 条
24
-
25
- | 上游提交 | 内容 | 判决 | 依据 |
26
- |---|---|---|---|
27
- | `7fe287b0d3` | abort 后停循环并落盘 aborted assistant 结局 | KEEP | design/118 State 机重写已覆盖:`aborted_before_stream` 终态(L583-591)、error/aborted 终态收割+合成 toolResult(L783-815,design/120 §5.4 + design/130 P2b),比上游补丁形态完整。 |
28
- | `56259606d1` | 只有 `stopReason==="toolUse"` 才派发工具;`removeNonExecutableToolCalls` 剥离截断调用 | KEEP(记设计立场差异) | 截断调用类:design/120 P2.0 契约已封死(`toolcall_end` 仅在输入 COMPLETE 且 JSON 有效时发,malformed 走 finalize 丢弃路径,`src/engine/llm/types.ts:449-461`;S2 恢复处理全丢场景)。剩余差异是**立场**:我们 length-stop 携完整工具调用时照常执行(④b 注释明确,L888),上游改为一律不派发——我们的是带恢复链的 deliberate 设计,不盲从。 |
29
- | `5ea80c8d80` | 工具 `execute` 返回/抛出后仍来的 onUpdate 回调被丢弃(`acceptingUpdates` 门) | **PORT ③(LOW)** | 我们 `executePreparedToolCall`(agent-loop L1771-1817)无此门:不守规矩的工具在 resolve 后再调 onUpdate 会在 `tool_execution_end`/结果落盘**之后**再发 `tool_execution_update`,事件序违约。三行零风险端口。 |
30
- | `0314819f91` | prose 终局分类器换掉(agents 层) | IGNORE | 上游 embedded-runner 私有面。 |
31
-
32
- ### C. 工具参数校验(validation)— 3 条
33
-
34
- | 上游提交 | 内容 | 判决 | 依据 |
35
- |---|---|---|---|
36
- | `9202dbb1b6` | 字符串化 JSON 数组/对象参数(`'["a","b"]'`)先 JSON.parse 再校验(MiMo/Ollama 类 provider) | **PORT ②** | 我们 `src/engine/llm/validation.ts` 无 JSON.parse 协迫路径;弱 provider(我们真跑 DeepSeek/Qwen/网关)确会字符串化复杂参数。与我们 fail-closed 宪法兼容:parse 出的候选仍须过 `validator.Check` 才接受,不通过原样拒。 |
37
- | `361869e434` | anyOf 联合里 null 不再被协迫成 "" | KEEP | 我们的 union 协迫走 `coerceWithUnionSchema`(clone→coerce→**Check 通过才接受**,L205-215),且有更严的 null 双向不虚构宪法(A1 + mod #22,L95-102/153-158)。 |
38
- | `c030b305a4` | 模板参数 tokenizer 保留空引号参数 `""` | IGNORE | 上游 slash-command 模板参数展开;我们侧该资源面从未接线(agent-harness L958 注释),tokenizer 不存在。 |
39
-
40
- ### D. 执行环境(exec/process)— 3 条
41
-
42
- | 上游提交 | 内容 | 判决 | 依据 |
43
- |---|---|---|---|
44
- | `e779abf70e` | NodeExecutionEnv.exec 给 child.stdout/stderr 挂 `error` 监听(EPIPE → 未捕获异常炸整进程) | **PORT ④** | 我们 `src/engine/execution-env/node-execution-env.ts` exec 路径只挂了 `child.on("error")`(L609),stdout/stderr 流本身无 error 监听(L586-607);流 EPIPE = 未捕获异常炸宿主。同文件 L178 起的辅助 exec 同缺。小而零风险。 |
45
- | `55fa22b482` | taskkill spawn 错误处理(spawn 错误是异步 `error` 事件,不是同步 throw) | **PORT ⑤(LOW,win32)** | 我们 `kill-tree.ts` `runTaskkill`(L112-120)只有 try/catch 包 spawn,spawn 的异步 error 事件无监听 → ENOENT/EPERM 时未捕获 `error` 事件炸进程。一行 `.on("error", noop)`。win32 面本就标注未真机验([379])。 |
46
- | `78399a194c` | localize exec timeout helper | IGNORE | 纯重构。 |
47
-
48
- ### E. 会话/缓存/用量 — 4 条
49
-
50
- | 上游提交 | 内容 | 判决 | 依据 |
51
- |---|---|---|---|
52
- | `1a002c2d9d` | prompt 释放期并发转写更新跨 stale session manager 保留 | IGNORE | 上游 session-manager 并发模型;我们有 F2 乐观锁 seam(`expectedLeafId` CAS)防树分叉,架构不同。 |
53
- | `f5931f5516` | 活跃轮 inbound 元数据挪到尾部 runtime-context 消息,保 byte-stable prompt cache | IGNORE(WATCH 原则) | 上游 channel 元数据装饰面我们没有。**原则记档**:任何「活跃轮装饰≠历史回放字节」的注入都会每轮打穿前缀缓存——我们 reminders/attachWorkingFiles 类注入若改形态,须守「落盘什么就回放什么」。 |
54
- | `53580e13a4` | provider 计费 0 值保留 + openrouter 延迟 generation 元数据重试 | IGNORE | 上游 usage/cost provenance 模型;我们 `totalTokens \|\|` 兜底不受 0 值类问题影响(0 会落到求和分支,行为正确)。 |
55
- | `614e87cce1` | 依赖升级 | IGNORE | 内务。 |
56
-
57
- ### F. 新特性/内务 — 12 条
58
-
59
- `f305e707a3`/`1f6ddb5df0`(Mythos 5 / Sonnet 5 模型目录)= IGNORE(我们模型面配置驱动,无内置目录);`0acd851a3b`(managed git worktree 生命周期 create/provision/snapshot/restore/GC)= IGNORE-参考(我们 1.255 已自研 Worktree 工具对,GC 思路可日后对照);`965fa05df3`(tool search directory mode)= IGNORE(我们 ToolSearch=design/36 延迟披露,设计不同);`062f88e3e3`/`65a9cb4ed1`/`49cc59b1e8`/`328a44695f`/`464adfe5e5`(重构/deadcode)、`95ebb3dc1e`(TUI)、`3d404478b8`(Discord)、`19617b0b45`(grep 截断劈 surrogate pair —— KEEP:我们 fs 截断已 surrogate-safe,`src/tools/fs/index.ts:702` + core/arg-summary/exec-gate/untrusted-text 全族早修过)= 均不动。
60
-
61
- ## PORT 候选汇总(5 条,按优先级)
62
-
63
- 1. **PORT ①(MED)** `2ece2945ae` 同类:`estimateTokens` user 分支补 image(+document)计权 — 我们代码坐实同 bug。
64
- 2. **PORT ②(MED)** `9202dbb1b6` 同类:validation 加「字符串化 JSON 数组/对象 → parse→Check 通过才接受」协迫路径。
65
- 3. **PORT ④(MED-LOW)** `e779abf70e` 同类:node-execution-env 两处 exec 给 stdout/stderr 挂 error 监听(防 EPIPE 炸宿主)。
66
- 4. **PORT ⑤(LOW)** `55fa22b482` 同类:kill-tree `runTaskkill` 给 spawn 子进程挂 error 监听(win32)。
67
- 5. **PORT ③(LOW)** `5ea80c8d80` 同类:`executePreparedToolCall` 加 `acceptingUpdates` 门,封死迟到 onUpdate 的事件序违约。
68
-
69
- 五条全是小切片、与现宪法(fail-closed/事件契约)同向,可并一个小修批;PORT ① ② 建议配对差分验收([417] 纪律)。
70
-
71
- ## 仓内残引扫描(步骤 3)
72
-
73
- - `grep -rn "openclaw|vendored" src/ --include="*.ts"`(排除 test):命中集中在 `src/engine/`(agent-harness 11、agent-loop 10、node-execution-env 10、runtask 8 等),**全部为注释性出处标注**(`VENDORED EDIT` provenance / openclaw 行为对照注释)。
74
- - **实码依赖检查**:`grep "from '.*vendor|require(.*vendor|from '.*openclaw'"` = **0 命中**。无 HIGH。
75
-
76
- ## npm pack 复核(步骤 4)
77
-
78
- `npm pack --dry-run | grep -i vendor` 仅命中 3 个 **docs 文件名**(`docs/audit-2026-06-12-…vendored死路.md`、`docs/audit-2026-06-15/VENDOR-REFACTOR-PLAN.md`、`docs/vendor-history.md`)——均为出处/历史文档,**零代码残引**。PASS。
79
-
80
- ## 下月 baseline
81
-
82
- - **新 baseline:`53d0c4ca50`**(origin/main @ 2026-07-07)。
83
- - 参照面不变:`packages/agent-core` + `packages/llm-core`(必要时加 `packages/ai` 的 Usage 形状观察,见 e6ec74c254 WATCH)。