@kodax-ai/kodax 0.7.84 → 0.7.86

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 (93) hide show
  1. package/CHANGELOG.md +218 -5
  2. package/README.md +1888 -1850
  3. package/README_CN.md +1146 -1137
  4. package/dist/chunks/agent-IO6TXNCV.js +2 -0
  5. package/dist/chunks/argument-completer-JMICSGL6.js +2 -0
  6. package/dist/chunks/chunk-2RAXDUC7.js +379 -0
  7. package/dist/chunks/chunk-A5VQGXH2.js +2 -0
  8. package/dist/chunks/{chunk-OHZFGQEH.js → chunk-AAFFS6RU.js} +2 -2
  9. package/dist/chunks/chunk-B36G256E.js +679 -0
  10. package/dist/chunks/chunk-G5FGIRDJ.js +1278 -0
  11. package/dist/chunks/chunk-GVGLYVG4.js +5 -0
  12. package/dist/chunks/chunk-MFCPQZ7E.js +519 -0
  13. package/dist/chunks/chunk-Q6UAGROD.js +415 -0
  14. package/dist/chunks/chunk-R4EHASEN.js +319 -0
  15. package/dist/chunks/chunk-U6HNMLNN.js +410 -0
  16. package/dist/chunks/chunk-UH5WNJXF.js +92 -0
  17. package/dist/chunks/{chunk-WTYAZOWO.js → chunk-UKCDCVMD.js} +1 -1
  18. package/dist/chunks/chunk-XA4ENCAH.js +412 -0
  19. package/dist/chunks/{chunk-ZVPTDYDI.js → chunk-XUKLF26Q.js} +2 -2
  20. package/dist/chunks/compaction-config-5RMG22CY.js +2 -0
  21. package/dist/chunks/{construction-bootstrap-EVQ6VWSX.js → construction-bootstrap-4DGAYOWH.js} +1 -1
  22. package/dist/chunks/dist-DFW7MXT7.js +2 -0
  23. package/dist/chunks/host-6MMHYTI5.js +2 -0
  24. package/dist/chunks/run-manager-ISQSWCAM.js +2 -0
  25. package/dist/chunks/utils-LV7FHKYN.js +2 -0
  26. package/dist/index.d.ts +17 -15
  27. package/dist/index.js +2 -2
  28. package/dist/kodax_bootstrap.js +1 -1
  29. package/dist/kodax_cli.js +2074 -1615
  30. package/dist/kodax_resume.js +271 -90
  31. package/dist/runtime-worker.js +1812 -1359
  32. package/dist/sandbox-workspace-session.js +1069 -112
  33. package/dist/sdk-a2a.d.ts +11 -10
  34. package/dist/sdk-a2a.js +9 -8
  35. package/dist/sdk-agent.d.ts +39 -299
  36. package/dist/sdk-agent.js +1 -1
  37. package/dist/sdk-coding.d.ts +103 -16
  38. package/dist/sdk-coding.js +1 -1
  39. package/dist/sdk-experimental-memory.d.ts +7 -20
  40. package/dist/sdk-experimental-memory.js +1 -1
  41. package/dist/sdk-mcp.js +1 -1
  42. package/dist/sdk-media.js +1 -1
  43. package/dist/sdk-repl.d.ts +14 -15
  44. package/dist/sdk-repl.js +2 -2
  45. package/dist/sdk-runtime.d.ts +73 -24
  46. package/dist/sdk-runtime.js +1 -1
  47. package/dist/sdk-sandbox.d.ts +1 -1
  48. package/dist/sdk-sandbox.js +1 -1
  49. package/dist/sdk-session.d.ts +7 -6
  50. package/dist/sdk-session.js +1 -1
  51. package/dist/sdk-skills.d.ts +2 -2
  52. package/dist/sdk-skills.js +1 -1
  53. package/dist/semantic-worker.js +250 -64
  54. package/dist/types-chunks/{bash-prefix-extractor.d-CkdGL4rM.d.ts → bash-prefix-extractor.d-QqKtuLZm.d.ts} +137 -14
  55. package/dist/types-chunks/{capsule.d-7wQ_kM1C.d.ts → capsule.d-CN_iMqAS.d.ts} +2 -1
  56. package/dist/types-chunks/controller.d-A73Kf6tH.d.ts +105 -0
  57. package/dist/types-chunks/{controller.d-CesRxFL5.d.ts → controller.d-Dzxz22X-.d.ts} +26 -1020
  58. package/dist/types-chunks/{guardrail.d-KaIeVree.d.ts → guardrail.d-Y_AIh8-I.d.ts} +21 -21
  59. package/dist/types-chunks/{history-retrieval.d-CbCls7r0.d.ts → history-retrieval.d-Debbzn1z.d.ts} +1 -1
  60. package/dist/types-chunks/{public-api.d-DpRj8b7d.d.ts → public-api.d-Cg-4GTbK.d.ts} +3 -2
  61. package/dist/types-chunks/{repl.d-DWeC3PLW.d.ts → repl.d-Bhrbueab.d.ts} +5 -5
  62. package/dist/types-chunks/review-inbox.d-DuZqFX-z.d.ts +221 -0
  63. package/dist/types-chunks/{run-manager.d-BXBkLT0A.d.ts → run-manager.d-BS4lJfL3.d.ts} +1 -1
  64. package/dist/types-chunks/{sdk-session-DEtS6u20.d.ts → sdk-session-fQ_KENev.d.ts} +2 -2
  65. package/dist/types-chunks/{shell-command-sets.d-P2h4_KKL.d.ts → shell-command-sets.d-DRGjd_7Q.d.ts} +3 -2
  66. package/dist/types-chunks/{types-Bf3Y3mW-.d.ts → types-PHjfwebT.d.ts} +62 -190
  67. package/dist/types-chunks/{types.d-0m3PS7Ng.d.ts → types.d-BRrJU4pb.d.ts} +2 -2
  68. package/dist/types-chunks/{types.d-BbtGlKZu.d.ts → types.d-BSPlmJqf.d.ts} +25 -6
  69. package/dist/types-chunks/{types.d-CUtMr2IG.d.ts → types.d-Bo4fyMLu.d.ts} +1 -1
  70. package/dist/types-chunks/types.d-DlLBRqZ9.d.ts +1057 -0
  71. package/dist/types-chunks/{utils.d-C-eSIZ9n.d.ts → utils.d-BIhh_BqE.d.ts} +7 -4
  72. package/package.json +4 -2
  73. package/dist/chunks/agent-VMXNVYRK.js +0 -2
  74. package/dist/chunks/argument-completer-QCS6GUAE.js +0 -2
  75. package/dist/chunks/chunk-4ZI2CPUQ.js +0 -885
  76. package/dist/chunks/chunk-6UENDY33.js +0 -89
  77. package/dist/chunks/chunk-726WJGGY.js +0 -2
  78. package/dist/chunks/chunk-A7L7XTUH.js +0 -292
  79. package/dist/chunks/chunk-BBBS644N.js +0 -319
  80. package/dist/chunks/chunk-E7C4DRD2.js +0 -5
  81. package/dist/chunks/chunk-ET2BMEQQ.js +0 -655
  82. package/dist/chunks/chunk-EVXIJPZ6.js +0 -218
  83. package/dist/chunks/chunk-F44YYR6Z.js +0 -479
  84. package/dist/chunks/chunk-GRLC3N46.js +0 -385
  85. package/dist/chunks/chunk-KHEFUT6O.js +0 -5
  86. package/dist/chunks/chunk-TDJS5SFS.js +0 -348
  87. package/dist/chunks/chunk-WXHHZZRJ.js +0 -379
  88. package/dist/chunks/compaction-config-QTMFP7AF.js +0 -2
  89. package/dist/chunks/dist-XRH6CRLL.js +0 -2
  90. package/dist/chunks/host-F4TPD6WY.js +0 -2
  91. package/dist/chunks/run-manager-PYD46OGY.js +0 -2
  92. package/dist/chunks/utils-TOTTXU2I.js +0 -2
  93. package/docs/SDK_EMBEDDER_GUIDE.md +0 -5752
package/CHANGELOG.md CHANGED
@@ -6,7 +6,220 @@ All notable changes to this project will be documented in this file.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- No changes yet.
9
+ ---
10
+
11
+ ## [0.7.86] - 2026-08-14
12
+
13
+ > Git tag and GitHub Release are created by the release workflow. npm
14
+ > publication remains a separate manual operator step.
15
+
16
+ ### Fixed
17
+
18
+ - Windows sandbox doctor and required Shell calls now surface actionable ACL
19
+ crash-recovery guidance for legacy or corrupt owner markers instead of a
20
+ generic unavailable result. Sandbox setup is serialized with owner admission
21
+ and cannot mutate account, guard, or WFP state while any sandbox owner or
22
+ unresolved poison marker exists for the shared Windows sandbox account. New owner markers
23
+ remain readable by older runtimes, while atomic-write staging files are kept
24
+ outside the legacy marker directory.
25
+ - Windows workspace Shell sessions now derive bounded read grants from each
26
+ command's final PATH and shell executable. Existing lexical and canonical
27
+ directories are admitted exactly; junction targets receive only the minimum
28
+ traversal ancestors below their profile application root, so version managers,
29
+ shims, virtual environments, and sibling runtime files work without naming
30
+ individual tools or exposing broad Documents/AppData vendor trees. Windows
31
+ shares one effective policy scope across compatible commands and confirms ACL
32
+ reset before switching to an incompatible scope. Standalone SDK calls,
33
+ workspace sessions, and duplicate SDK module copies use the same machine-wide
34
+ policy-owner protocol across Runtime profiles and KodaX homes, so incompatible
35
+ grants cannot combine through the shared Windows sandbox identity. The
36
+ target receives a case-normalized environment and preserves the Windows
37
+ verbatim-argument contract, so
38
+ profile-managed executables and quoted path arguments survive both broker layers.
39
+ - Auto-started Runtime clients now require sandbox execution capability v3, so
40
+ an idle daemon from KodaX 0.7.85 or the earlier v2 execution policy is replaced only after its durable shutdown
41
+ outcome and Windows Job supervisor prove the old process tree is empty. A
42
+ daemon without that verification contract remains fail-closed and must be
43
+ stopped explicitly before the repaired Shell chain is exposed.
44
+ - The first upgrade from a Runtime that predates the machine-wide Windows
45
+ sandbox-owner protocol requires all unmanaged legacy KodaX/Space processes
46
+ (including standalone SDK processes using another KodaX home) to be stopped.
47
+ Those binaries cannot participate in the new global owner lock; current and
48
+ future runtimes are serialized machine-wide after the transition.
49
+ - Clean Windows workspace-session shutdown now honors the sandbox runtime's full
50
+ ACL reset budget before escalating to process-tree termination, while unclean
51
+ or unverified exits remain durably fail-closed.
52
+ - Windows Shell sessions now share one ACL policy group when their normalized
53
+ workspace, Agent Home access, additional filesystem permissions, toolchain
54
+ scopes, and network policy are identical. Compatible commands can run in
55
+ parallel across independent KodaX processes; the last policy-group member confirms
56
+ reset before releasing its owner. Different policies fall back immediately
57
+ to the already-authorized ordinary execution path instead of blocking on a
58
+ machine-wide sandbox fence. Preparation failures use the same fallback, while
59
+ a command that started or may have started is never replayed implicitly.
60
+ - Filesystem-effect coordinator handoff now waits through the lock protocol's
61
+ 30-second stale-owner safety window. Slow or rapid cross-process handoffs no
62
+ longer fail at five seconds, while real cross-category effect conflicts keep
63
+ their existing one-second fail-closed admission boundary.
64
+ - Runtime Shell containment is now sandbox-first rather than sandbox-required.
65
+ Auto[LLM] remains the single authorization decision, successful allow results
66
+ are cached only for the same Runtime-session intent revision, and unavailable
67
+ sandbox infrastructure uses normal permission enforcement without another
68
+ classifier call. Catastrophic root deletion, disk formatting/raw disk writes,
69
+ fork bombs, and Agent Home root/control-plane destruction remain deterministic
70
+ hard denials. The obsolete public `failClosed` switch has been removed.
71
+ - The packaged Electron regression smoke now runs 20 Runtime Shell commands
72
+ through a profile-added junction toolchain, resolves the packaged Node binary
73
+ through its version-manager ancestry, exercises a quoted `cmd.exe` path, and
74
+ keeps its probe I/O inside the admitted workspace.
75
+ - Packaged Electron hosts on Windows now keep Electron's Node bootstrap mode
76
+ across the internal filesystem-effect gate without leaking it to user
77
+ commands. Sandbox readiness uses KodaX's staged runner outside ASAR, failed
78
+ workspace sessions are retired, stale ACLs are recovered before startup and
79
+ after the last compatible sandbox owner exits, and an execution with missing
80
+ attestation is reported without replaying a possibly side-effecting command.
81
+ - Sandbox stop now waits for process-tree termination proof before ACL recovery;
82
+ undrained Shell effects and spawn/cleanup failure combinations are reported as
83
+ lifecycle safety errors. Windows ACL owner markers admit only an exact shared
84
+ policy group for the machine sandbox identity, and crash recovery is serialized
85
+ across Runtime profiles.
86
+ - Inline Runtime owner recovery now removes only a provably abandoned inline
87
+ owner fence before restoring daemon policy. Live, unreadable, legacy-kind,
88
+ daemon-kind, and unverifiable owners remain fail-closed, while a failed
89
+ inline-owner release remains retryable.
90
+ - Runtime owner records and learning-file locks now retain an OS process-start
91
+ identity, so a reused PID cannot keep stale ownership alive.
92
+ - Windows sandbox lifecycle failures now wait for termination proof, preserve
93
+ cleanup evidence, fence later filesystem effects, and never replay a command
94
+ whose effect process was not proven drained.
95
+ - POSIX sandbox workspace sessions now latch an unconfirmed process-tree or
96
+ cleanup failure and reject replacement sessions until the safety state is
97
+ reset, matching the fail-closed lifecycle contract across platforms. Fresh
98
+ `KODAX_HOME` policy roots are initialized before policy identity is captured,
99
+ concrete admissions wait only for their workspace-local warm-up within the
100
+ existing Shell abort/deadline, and a failed lease cleanup retires the invalid
101
+ cached session before replacement.
102
+
103
+ ---
104
+
105
+ ## [0.7.85] - 2026-08-11
106
+
107
+ > Git tag and GitHub Release are created by the release workflow. npm
108
+ > publication remains a separate manual operator step.
109
+
110
+ ### Changed
111
+
112
+ - Runtime event ordering is now Session-scoped. Every event carries a
113
+ `{ sessionId, journalEpoch, seq }` cursor; public subscribe/replay calls must
114
+ specify `sessionId` or `runId`, and replay resumes from `after` rather than a
115
+ Runtime-global numeric sequence. Independent Sessions no longer contend on
116
+ one `event-sequence.lock`.
117
+ - A2A assigns one Runtime Session to each A2A Task and persists that Session
118
+ cursor in a small progress checkpoint for recovery, avoiding a full
119
+ `tasks.json` rewrite per micro-event. Only semantic task-state transitions
120
+ are projected to the A2A stream; token/tool progress remains Runtime telemetry.
121
+ - Daemon clients require the `sessionEventJournal:1` capability. Legacy global
122
+ Runtime event logs remain on disk for audit but are not mixed into live
123
+ Session replay.
124
+ - Session failure latches and retention watermarks are journal-scoped. Reusing
125
+ a deleted Session ID rotates the epoch, ambiguous Windows path components remain
126
+ distinct, malformed cursors and mismatched Session/Run scopes fail closed,
127
+ legacy watermarks without an epoch cannot poison new replay, and a durable
128
+ per-Run journal index keeps fully trimmed child journals attributable if a
129
+ watermark is later corrupted. Missing or corrupt index evidence fails closed
130
+ instead of treating an ambiguous trimmed journal as unrelated.
131
+
132
+ ### Fixed
133
+
134
+ - Memory/Learning command output is now rendered through the Ink-captured
135
+ command channel instead of raw stdout. `/learn` reports an explicit empty
136
+ state, `/learn ready` is the canonical ready-capability query, and the legacy
137
+ `/learn pending` alias explains that it is unrelated to episode-review work.
138
+ Memory management is now conversation-first: explicit remember, correction,
139
+ forget, recall, and exceptional-decision requests use one governed hidden tool.
140
+ Safe explicit mutations apply immediately; stable semantic claim keys make
141
+ later contradictions address the same fact/preference/policy/procedure slot.
142
+ A host-owned handled-operation marker prevents the instruction from being duplicated
143
+ into the outcome review, while the rest of the episode still participates in
144
+ autonomous Memory/Skill learning. Ambiguity and broad input request
145
+ clarification, conflicts become readable decisions, secrets are rejected,
146
+ and inferred changes stay governed. `/memory` remains a compact advanced escape hatch for accepted
147
+ Memory, decisions, diagnostics, and external-editor opening. Raw review/status
148
+ and derived-index rebuild commands remain hidden diagnostics; `MEMORY.md` is a
149
+ projection rather than the source of truth. The
150
+ `@kodax-ai/kodax/experimental-memory` factory now returns an additive
151
+ `MemoryManagementAgent` only for a management-capable controller, exposing
152
+ list, remember, and forget without widening the existing
153
+ `MemoryAgent`/`MemoryController` structural contracts. Natural-language
154
+ decision handles carry their preview revision across turns and fail closed if stale.
155
+ - Unified Memory review accepts a minimal model-owned action/warning plan and
156
+ binds trigger, timestamps, source/candidate references, and digest authority
157
+ on the host. This removes redundant schema work that caused GLM providers to
158
+ return invalid plans without weakening deterministic action validation.
159
+ - Issue 282 follow-up: Actor progress is now batched once per controller tree,
160
+ terminal persistence excludes known mutation-queue waits from its five-second
161
+ ambiguity budget, and a permanently blocked predecessor remains bounded by a
162
+ separate queue-wait fence. Progress promises also reject when an ownership
163
+ conflict self-fences their controller instead of remaining pending forever.
164
+ - A durability-unknown Actor tree now fail-closes its owning root executor and
165
+ automatically reconciles only an exact same-owner late snapshot. Runs settle
166
+ as `actor_settlement_not_persisted` unless a stronger executor Promise fact
167
+ was captured before the fence. Same-owner durable repair plus root abort and
168
+ post-fence admission suppression closes the Session route after every exact
169
+ tool execution admitted before the fence has settled. It does not wait for
170
+ an abort-ignoring provider Promise; callbacks and new Runtime-mediated effects
171
+ from the fenced root remain blocked.
172
+ - Healthy `after_turn` input keeps the established coding-mode default. It
173
+ inherits a managed predecessor's mode only when it actually drains behind an
174
+ Actor durability repair.
175
+ - Self-fenced Actor admission now reports the causal settlement-persistence
176
+ error instead of the misleading `actor_owner_conflict`. Genuine foreign-owner
177
+ conflicts remain fail-closed.
178
+ - Runtime capability negotiation now exposes `actorSettlementConvergence:1`,
179
+ including automatic repair and safe after-turn queueing behind an unknown Run.
180
+ - Issue 286: Learned Skill discovery now traverses the distinct remote and local
181
+ hashed project roots and routes every canary mutation to the record's owning
182
+ store. `remote-hash:*` receives the same local fallback, while the public
183
+ deprecated `expectedScope` configuration remains source/runtime compatible
184
+ with the optional multi-scope form.
185
+ - Issue 285: Rules-mode agent-home access now protects the home root from whole-
186
+ tree removal, hard-denies Runtime mutations, and reviews credential/security
187
+ config plus generic sensitive filenames.
188
+ The legacy `processes/children` registry is now treated as host control state:
189
+ model writes are hard-denied, and upgrade cleanup quarantines unauthenticated
190
+ historical records without using them to signal a process.
191
+ Learned Area persistence is also host-owned and no longer directly writable
192
+ by model file or shell tools.
193
+ Ordinary descendants—including `agents/*.md`, Sessions, tool results, and
194
+ intermediate artifacts—remain readable and writable without approval.
195
+ - Issue 285 execution-time file sinks now recheck the hard boundary after
196
+ queueing. Undo backups are context-scoped and identity-fenced, while workflow
197
+ worktree roots are accepted only through the trusted controller context.
198
+ Agent Home root and Runtime shell mutations use a non-authorizable gate in
199
+ both Auto[LLM] and Auto[Rules]; sensitive configuration remains reviewable.
200
+ A cross-process category lease prevents model-started shell effects from
201
+ racing a privileged file sink's canonical check and write without serializing
202
+ independent shell calls or independent direct-file mutations.
203
+ - Every coding run now carries a non-removable Agent Home shell boundary.
204
+ Opaque Bash requires a fail-closed OS sandbox with authoritative process-tree
205
+ containment; unsandboxed or filesystem-only standalone callers
206
+ may run only completely modeled exact commands. Runtime supplies that sandbox
207
+ in every permission mode and fails closed when preparation is unavailable.
208
+ Linux uses the built-in ASRT PID namespace and Windows adds a per-effect Job;
209
+ macOS and legacy custom adapters without the optional containment capability
210
+ retain exact modeled commands but fail closed for opaque Bash.
211
+ Protected Agent Home reads still require review, but are not permanently
212
+ denied by the OS sandbox after an explicit approval.
213
+ On Windows, ACL grants target verified ordinary Agent Home children rather
214
+ than the Home object itself, so `agents`, Sessions, and intermediate results
215
+ remain writable without granting permission to delete the whole Home root.
216
+ - Session event replay now rejects cursors ahead of the current journal instead
217
+ of silently returning no events. Limited replay retains the latest-event
218
+ behavior without a cursor and returns the earliest forward page when `after`
219
+ is supplied; replay limits must be positive safe integers. Corrupt aggregate
220
+ journal/status metadata is reported without widening the failure to unrelated
221
+ Sessions, valid retired journals are not misreported as corrupt, and A2A
222
+ regression coverage pins legacy numeric event positions as non-cursors.
10
223
 
11
224
  ---
12
225
 
@@ -2022,7 +2235,7 @@ No changes yet.
2022
2235
 
2023
2236
  - **`code_search` / `semantic_lookup` teaching in the Worker REPO INTELLIGENCE prompt (FEATURE_250).** A two-line, eval-justified teaching block: the floor-tier alias under-adopted the hint-only tools on ambiguous tasks (75%), and the teaching recovered adoption to 100% while being strictly non-negative on every other alias.
2024
2237
  - **CAP-099 live turn attribution — session/turn identity on streamed events (Space SDK).** A shared live-turn scope (`createLiveTurnScope` / `withLiveTurnAttribution`, `event-emitter.ts`) stamps `KodaXActivityEventMeta` (`sessionId` / `seq` / `turnId` / `deliveryId` / `timestamp`) onto every streamed activity callback, and explicit turn-boundary events (`emitTurnStarted` / `emitTurnCompleted` / `emitTurnFailed`) share one monotonic per-session sequence — so an SDK host can route streamed assistant events to the owning turn's UI bubble by turn ownership instead of fragile ordering-by-observation. Threaded through messaging (queue/drain), orchestration (idle-yield), run-substrate, runner-driven, run-workflow, and dispatch-child-tasks; a host that ignores the metadata sees unchanged behavior. New `cap-099-live-turn-attribution` contract test; existing `cap-005/006/007/041/046/054/086` event-contract tests updated for the added meta parameter.
2025
- - **Client-only transcript notices + structured transcript entries (CAP-099, Space SDK).** The persisted transcript gains structured entry types (`message` / `compaction` / `branch_summary` / `client_notice` / `task_result`) with `source` + `turnId`. A `client_notice` is persisted as a lineage entry, NOT a model message: `loadSession()` (active model context) omits it while `loadFullTranscript()` returns it with `type: 'client_notice'`, `source: 'client'`, and `payload.entersModelContext === false` — so a host can render client-side scrollback notices without polluting the model's context. SDK embedder guide updated (`docs/SDK_EMBEDDER_GUIDE.md`).
2238
+ - **Client-only transcript notices + structured transcript entries (CAP-099, Space SDK).** The persisted transcript gains structured entry types (`message` / `compaction` / `branch_summary` / `client_notice` / `task_result`) with `source` + `turnId`. A `client_notice` is persisted as a lineage entry, NOT a model message: `loadSession()` (active model context) omits it while `loadFullTranscript()` returns it with `type: 'client_notice'`, `source: 'client'`, and `payload.entersModelContext === false` — so a host can render client-side scrollback notices without polluting the model's context. SDK embedder guide updated (`public_docs/sdk/embedder-guide.md`).
2026
2239
  - **Transcript clone provenance for SDK hosts (CAP-099, Space SDK).** Lineage entries now carry optional `logicalId` / `sourceEntryId`, and `loadFullTranscript().transcriptEntries[]` always exposes a stable `logicalId` (falling back to `entryId` for old sessions). Forked/cloned entries keep the source `logicalId` and point `sourceEntryId` at the root physical source entry, so hosts can fold cloned history precisely without guessing from role/content/timestamp or `[compacted]` placeholders. `loadFullTranscript()` remains raw append-order scrollback; it does not silently merge branches or hide compaction notices.
2027
2240
 
2028
2241
  ### Changed
@@ -2369,7 +2582,7 @@ No changes yet.
2369
2582
  ### Added
2370
2583
 
2371
2584
  - **FEATURE_132 — Native LSP integration: edit-time diagnostics reflux (TS/JS, Python, Go, Rust, Java).** After the `write` / `edit` / `multi_edit` tools change a file, KodaX now opens it through a language server and refluxes any type ERRORs straight back into the tool result, so the agent fixes them the same turn instead of waiting for the next build (saving ≥1 LLM round-trip). Servers are discovered on `PATH` / project `node_modules` (typescript-language-server, pyright, gopls, rust-analyzer, jdtls); when none is installed the feature is **silent** (no nagging), and a one-shot blacklist + spawn-dedup keep it cheap. It is **default-on but self-limiting**: only ERROR severity, ≤20 per file, a 5s per-file wait that runs OUTSIDE the file-mutation lock, and `KODAX_LSP=0` disables it entirely. Auto-installing a missing server is **opt-in** (`KODAX_LSP_DOWNLOAD=1`; `KODAX_LSP_NO_DOWNLOAD=1` hard-off) — KodaX never runs `go install` / `npm i` unprompted. The LSP TypeScript server runs as its own subprocess, isolated from the in-process repo-intelligence TS engine. It also adds four read-only navigation tools — `lsp_definition` / `lsp_hover` / `lsp_references` / `lsp_document_symbols` — for precise, position-anchored, real-time questions about the current code (complementing the repo-scope repo-intelligence symbol tools; the tool descriptions teach the boundary). Implemented under `packages/coding/src/lsp/`; new exports from `@kodax-ai/coding`: `LspService`, `getDefaultLspService`, `shutdownDefaultLspService`, `languageIdForPath`. See [docs/features/v0.7.47.md FEATURE_132](docs/features/v0.7.47.md).
2372
- - **FEATURE_221 — Injectable self-manual for SDK consumers (`selfManual`).** Products built on the KodaX SDK (e.g. KodaX-Space) can now inject their **own** product manual so the built-in `kodax_manual` tool answers *their* users' "how do I use / configure …?" questions on-brand, instead of returning KodaX's internal manual. `runKodaX({ selfManual: { productName, topics } })` re-brands the ≤250-token routing rule + scope anchors to `productName` and **extend-merges** your `KodaXManualTopicInput[]` over KodaX's base topics (same `id` overrides, new `id` appends), so users can still ask about the underlying provider / config / SDK topics. **Opt-in and backward-compatible** — omit `selfManual` and the system prompt is byte-identical to before. Topics stay **tool-on-demand and 4 KB-capped**: nothing large is injected into the prompt, only the short routing rule. New exports from `@kodax-ai/coding`: `KodaXManualTopicInput`, `KodaXSelfManualConfig`, `ResolveKodaXManualOptions`, `buildSelfKnowledgeRoutingRule`. See [SDK Embedder Guide §13](docs/SDK_EMBEDDER_GUIDE.md#13-inject-your-products-manual--selfmanual-feature_221-v0747) + [docs/features/v0.7.47.md FEATURE_221](docs/features/v0.7.47.md).
2585
+ - **FEATURE_221 — Injectable self-manual for SDK consumers (`selfManual`).** Products built on the KodaX SDK (e.g. KodaX-Space) can now inject their **own** product manual so the built-in `kodax_manual` tool answers *their* users' "how do I use / configure …?" questions on-brand, instead of returning KodaX's internal manual. `runKodaX({ selfManual: { productName, topics } })` re-brands the ≤250-token routing rule + scope anchors to `productName` and **extend-merges** your `KodaXManualTopicInput[]` over KodaX's base topics (same `id` overrides, new `id` appends), so users can still ask about the underlying provider / config / SDK topics. **Opt-in and backward-compatible** — omit `selfManual` and the system prompt is byte-identical to before. Topics stay **tool-on-demand and 4 KB-capped**: nothing large is injected into the prompt, only the short routing rule. New exports from `@kodax-ai/coding`: `KodaXManualTopicInput`, `KodaXSelfManualConfig`, `ResolveKodaXManualOptions`, `buildSelfKnowledgeRoutingRule`. See [SDK Embedder Guide §13](public_docs/sdk/embedder-guide.md#13-inject-your-products-manual--selfmanual-feature_221-v0747) + [docs/features/v0.7.47.md FEATURE_221](docs/features/v0.7.47.md).
2373
2586
  - **FEATURE_218 — KodaX self-knowledge manual + `kodax_manual` help tool.** KodaX now ships a version-bound, structured product manual (17 topics: overview / install / providers / custom-providers / config / permissions / commands / tools / agents / skills / mcp / repo-intelligence / sessions / doctor / sdk / troubleshooting) behind a read-only `kodax_manual` tool, plus a ≤250-token routing rule that tells the model to look up KodaX usage/config questions instead of guessing or mixing in Claude Code / Codex CLI knowledge. The provider list is sourced from the single-source-of-truth capability snapshots (drift-proof, not hand-copied) and each answer is anchored to KodaX scope. REPL `/help <topic>` reuses the same registry. Lookup is deterministic (exact id → alias, incl. Chinese → query token-overlap → index) and never fabricates; single-topic output ≤4 KB, index ≤2 KB. No RAG, no vector DB, no background index, no prompt bloat. See [docs/features/v0.7.47.md FEATURE_218](docs/features/v0.7.47.md).
2374
2587
  - **MCP client — protocol `2025-11-25` compatibility (P0+P1).** KodaX's self-built MCP client now speaks the `2025-11-25` revision. **P0 (protocol compliance):** answers a server `ping` with an empty result instead of `-32601`; emits `notifications/cancelled` when a request times out (the `initialize` request is exempt); and resumes a dropped Streamable-HTTP notification stream via SSE `id`/`retry` + `Last-Event-ID`, with a reconnect cap so an empty-EOF stream can't reconnect-loop forever. **P1 (version + data surface):** advertises protocol `2025-11-25` with negotiation validation + the `MCP-Protocol-Version` header; carries tool/resource/prompt `icons` into descriptors (filtering unsafe URI schemes); and surfaces `execution.taskSupport`, failing fast on task-required tools. Unwired `elicitation` dead code removed. (Reverse / server-side capabilities are planned as FEATURE_222 for v0.7.48.)
2375
2588
 
@@ -2448,7 +2661,7 @@ shared names — the new name is required for the coding-plan provider to start.
2448
2661
  - **P2 — explicit per-dispatch override.** `dispatch_child_task` gains optional `provider` / `model` params, so the agent can deliberately send a child to another model family — e.g. a second independent review of the same change by a different family, to catch blind spots a single family would share. Resolution priority in `child-executor`: `bundle.provider/model` > specialist's declared model (FEATURE_191) > parent default. Omitting both is byte-identical to the prior behavior. Tolerant parse (empty/whitespace → undefined) so a misuse never fails the dispatch.
2449
2662
  - **P3 — cross-provider fallback + `doctor --ping`.** When a child's primary provider is *exhausted or down* (the LLM layer's same-provider `withRateLimit` retries gave up, a 5xx, or a network error), KodaX re-runs the child once on the next provider in an operator-configured chain instead of failing the whole child. Configured via `/fallback ark-coding,kimi-code` (persists to `~/.kodax/config.json` + mirrors to `KODAX_FALLBACK_PROVIDERS`; `/fallback off` to clear, `/fallback status` to inspect). Empty chain = OFF. Scope is deliberately minimal (per user direction): only hard availability errors trigger fallback — a returned `success:false` is a task outcome (not retried elsewhere) and aborts are never faked over; the speculative tool-call-fidelity / context-overflow / quality-anomaly triggers are unbuilt (YAGNI). `kodax doctor --ping` completes the health check: it sends one minimal request per configured provider (10s timeout, concurrent) to prove the key actually works and the subscription is active — opt-in, small token cost, never on the default `doctor`. 16 tests (11 fallback core + 5 `/fallback` command).
2450
2663
  - **P1-auto — `model_hint` → tier routing.** The previously dormant `model_hint` field (`fast`/`balanced`/`deep`, FEATURE_120) now selects an operator-configured tier: `fast` → `KODAX_FAST_PROVIDER`/`KODAX_FAST_MODEL` (**read-only children only** — the gating eval validated cheap-model quality on read-only investigation but not write/codegen, so write children stay on the parent tier), `deep` → `KODAX_DEEP_PROVIDER`/`KODAX_DEEP_MODEL` (read or write). `balanced`/unset, or any unconfigured tier, falls back to the parent — **routing is OFF by default** and turns on only when you point a tier env var at a model (no separate toggle). Specialist and explicit-P2 overrides both win over the hint. Per KodaX minimalism the original 5-name capability-alias layer (`vision`/`long-context`/…) was descoped to this env-tier form — no consumer exists for the rest yet (YAGNI). Pure routing wiring; the Worker prompt is unchanged (an eval non-trigger per `CLAUDE.md`), so $0 / no panel. Gating eval (`tests/feature-102-model-tier-quality.eval.ts`, canonical 5-alias × 3 read-only investigation × 5 run) kept as permanent regression: cheap floor `ark/v4flash` = 15/15, ≥ strong-mean 92% → cheap PRESERVES read-only quality. New unit + integration tests (7 `model-hint-routing` + 5 child-executor P2/P1-auto priority); also de-flaked the pre-existing `merges findings` child-executor test (parallel children made `mergeChildResults` emit in completion order — now deterministic dispatch order). Design: [docs/features/v0.7.45.md](docs/features/v0.7.45.md#phase-1--model_hint--真实跨-provider-子派发mvp).
2451
- - **FEATURE_216 — `verifyProviderCredential(name)` SDK API + per-provider strategy.** New top-level helper for SDK consumers (KodaX Space, third-party embedders) to validate a provider's API key against the actual upstream — never-throws, mostly zero-token. Closes the "test connection" UI gap: existing `isConfigured()` only checks env presence; `stream()`/`sideQuery()` are too heavy. Three primitives, one per provider, baked into `provider-capabilities.json` `verifyStrategy` field: **`count-tokens`** (Anthropic `messages.countTokens()`, 0 token) for `anthropic` + 4 anthropic-coding providers; **`models-list`** (`models.list()`, 0 token) for `openai`/`deepseek`/`kimi`/`qwen`; **`minimal-message`** (~6-7 token `chat.completions.create({max_tokens:1})`) for `zhipu`/`mimo`/`mimo-coding` (where `models.list()` is publicly-served or `count_tokens` returns 404). CLI-bridge providers (`gemini-cli`, `codex-cli`) return `unsupported` — their credentials live in the CLI binary's token store, outside SDK reach. Top-level `verifyProviderCredential(name, opts?)` short-circuits unknown name / unsupported strategy / missing env var BEFORE instantiating the provider class — avoids the constructor throw on missing key, and ALSO wraps the actual `verifyCredential()` call in try/catch so the never-throws contract survives runtime-registered providers whose 3rd-party overrides might throw instead of returning an envelope. Error categorization (`unauthorized` / `network` / `timeout` / `unsupported` / `unconfigured` / `server_error` / `rate_limited` / `unknown`) is stable for UI consumers to map to user-facing states — `rate_limited` (429) is distinct from `unauthorized` so a transiently throttled key isn't misread as invalid. The error `message` field redacts `sk-...` key fragments before truncation so upstream error bodies that echo the submitted key don't leak the fragment into UI logs. The `kimi-code`-specific 400→`unauthorized` mapping is gated by `providerName` to avoid false-positives on other count-tokens providers that might 400 on a legitimate bad request (bad model id / schema mismatch). Network error detection extended to `ETIMEDOUT` + `ENETUNREACH` + `EHOSTUNREACH` + `ENETDOWN` beyond the original `ENOTFOUND`/`ECONNREFUSED`/`ECONNRESET`/`EAI_AGAIN`/`EPIPE` set. Companion `listProviderModels(name)` returns the static curated list (always `source: 'static'` in v0.7.45 — upstream `/v1/models` is noisy + inconsistent across providers per the 2026-05-28 12-provider probe matrix). Custom providers auto-inherit by `protocol`; explicit `verifyStrategy` overrides allowed. 88 tests total (28 orchestrator + 14 resolver + 38 schema + 10 real-key integration gated on `KODAX_INTEGRATION_TEST=1`). Reference industry validator: opencode's `setup-recording-env.ts` makes the same per-provider decision across 20+ providers — per-provider strategy IS industry standard, no universal 0-token primitive exists. Design + probe data: [docs/features/v0.7.45.md#feature_216](docs/features/v0.7.45.md#feature_216-provider-credential-verification-api). SDK usage guide: [docs/SDK_EMBEDDER_GUIDE.md §12](docs/SDK_EMBEDDER_GUIDE.md#12-provider-credential-verification--verifyprovidercredential-feature_216-v0745).
2664
+ - **FEATURE_216 — `verifyProviderCredential(name)` SDK API + per-provider strategy.** New top-level helper for SDK consumers (KodaX Space, third-party embedders) to validate a provider's API key against the actual upstream — never-throws, mostly zero-token. Closes the "test connection" UI gap: existing `isConfigured()` only checks env presence; `stream()`/`sideQuery()` are too heavy. Three primitives, one per provider, baked into `provider-capabilities.json` `verifyStrategy` field: **`count-tokens`** (Anthropic `messages.countTokens()`, 0 token) for `anthropic` + 4 anthropic-coding providers; **`models-list`** (`models.list()`, 0 token) for `openai`/`deepseek`/`kimi`/`qwen`; **`minimal-message`** (~6-7 token `chat.completions.create({max_tokens:1})`) for `zhipu`/`mimo`/`mimo-coding` (where `models.list()` is publicly-served or `count_tokens` returns 404). CLI-bridge providers (`gemini-cli`, `codex-cli`) return `unsupported` — their credentials live in the CLI binary's token store, outside SDK reach. Top-level `verifyProviderCredential(name, opts?)` short-circuits unknown name / unsupported strategy / missing env var BEFORE instantiating the provider class — avoids the constructor throw on missing key, and ALSO wraps the actual `verifyCredential()` call in try/catch so the never-throws contract survives runtime-registered providers whose 3rd-party overrides might throw instead of returning an envelope. Error categorization (`unauthorized` / `network` / `timeout` / `unsupported` / `unconfigured` / `server_error` / `rate_limited` / `unknown`) is stable for UI consumers to map to user-facing states — `rate_limited` (429) is distinct from `unauthorized` so a transiently throttled key isn't misread as invalid. The error `message` field redacts `sk-...` key fragments before truncation so upstream error bodies that echo the submitted key don't leak the fragment into UI logs. The `kimi-code`-specific 400→`unauthorized` mapping is gated by `providerName` to avoid false-positives on other count-tokens providers that might 400 on a legitimate bad request (bad model id / schema mismatch). Network error detection extended to `ETIMEDOUT` + `ENETUNREACH` + `EHOSTUNREACH` + `ENETDOWN` beyond the original `ENOTFOUND`/`ECONNREFUSED`/`ECONNRESET`/`EAI_AGAIN`/`EPIPE` set. Companion `listProviderModels(name)` returns the static curated list (always `source: 'static'` in v0.7.45 — upstream `/v1/models` is noisy + inconsistent across providers per the 2026-05-28 12-provider probe matrix). Custom providers auto-inherit by `protocol`; explicit `verifyStrategy` overrides allowed. 88 tests total (28 orchestrator + 14 resolver + 38 schema + 10 real-key integration gated on `KODAX_INTEGRATION_TEST=1`). Reference industry validator: opencode's `setup-recording-env.ts` makes the same per-provider decision across 20+ providers — per-provider strategy IS industry standard, no universal 0-token primitive exists. Design + probe data: [docs/features/v0.7.45.md#feature_216](docs/features/v0.7.45.md#feature_216-provider-credential-verification-api). SDK usage guide: [public_docs/sdk/embedder-guide.md §12](public_docs/sdk/embedder-guide.md#12-provider-credential-verification--verifyprovidercredential-feature_216-v0745).
2452
2665
 
2453
2666
  ### Performance
2454
2667
 
@@ -2520,7 +2733,7 @@ shared names — the new name is required for the coding-plan provider to start.
2520
2733
 
2521
2734
  ### Added
2522
2735
 
2523
- - **FEATURE-SDK-MODEL-CAPS — Expose Per-Model Capabilities Without API Key** (2 commits `7f627d0c` feat + `c37b0a13` fix, shipped 2026-05-25). SDK consumers (KodaX Space etc.) need to list providers + their models with context-window / reasoning info in popout UIs — but the pre-v0.7.43 path forced instantiation of each `KodaXProvider` class, which throws on missing API key. Static metadata was hidden behind runtime credentials, an architectural mismatch — that data is KodaX-maintained, not negotiated with the upstream. **Fix** (2-part): (1) Promote capability metadata (`contextWindow` / `maxOutputTokens` / `thinkingBudgetCap` / `supportsThinking` / full `KodaXModelDescriptor[]`) from per-Provider `class.config` field initializers UP to the existing `KODAX_PROVIDER_SNAPSHOTS` constant — Provider classes now derive their runtime `config` from the snapshot via `buildProviderConfig` (single source of truth, no drift risk; net −160 lines duplication / +30 lines metadata / byte-equivalent runtime behavior). (2) Add 9 new SDK exports reading directly from the snapshot (zero API keys touched): built-in `getProviderModelDescriptors` / `getModelCapabilities` / `listBuiltinModelCapabilities`; custom (from `~/.kodax/config.json#customProviders`) `getCustomProviderModelDescriptors` / `getCustomModelCapabilities` / `listCustomProviderModelCapabilities`; unified dispatchers `resolveProviderModelDescriptors` / `resolveModelCapabilities` / `listAllModelCapabilities`. New public type `KodaXModelCapabilities` exposed from `@kodax-ai/kodax/llm`. **`maxOutputTokens` rationale** (fix commit `c37b0a13`): the field IS reliable — it's the KodaX-side per-turn `max_tokens` request decision (bench-validated against kill-windows / decode-rate / cost-per-turn), NOT the upstream "theoretical maximum" (which is often inflated or absent — zhipu-coding / kimi-code / minimax-coding / ark-coding / deepseek `/v1/models` returns `{id, object, owned_by, created}` only). Embedders showing "expected output size" should use this value; theoretical ceilings should be looked up from the upstream provider's own docs. **Maintainer-probe scripts shipped**: `scripts/probe-upstream-model-metadata.mjs` (re-run periodically to detect upstream API improvements) + `scripts/probe-ark-tokens.mjs` (Ark-specific drill-down). **Tests**: `packages/llm/src/providers/model-capabilities.test.ts` 20/20 ✓ (no-API-key verification clears 6 env vars during assertion; snapshot drift guard asserts every `supportsThinking` provider declares `contextWindow` + every `models[]` entry is a descriptor object); full llm suite 304/304 ✓. **Bundle impact**: `dist/sdk-llm.d.ts` +1.2 kB (new types + symbols); `dist/sdk-llm.js` +400 bytes. **Architectural debt followup**: `KODAX_PROVIDER_SNAPSHOTS` still TS const compiled into bundle; capability data update path still needs `npm publish` + consumer `npm update`. FEATURE_198 (filed for v0.7.44) splits the snapshot to JSON + runtime loader for dist-patch-time updates (hot-update over network deferred to v0.7.46+). Docs: [`SDK_EMBEDDER_GUIDE.md §9`](docs/SDK_EMBEDDER_GUIDE.md#9-querying-per-model-capabilities-without-api-keys).
2736
+ - **FEATURE-SDK-MODEL-CAPS — Expose Per-Model Capabilities Without API Key** (2 commits `7f627d0c` feat + `c37b0a13` fix, shipped 2026-05-25). SDK consumers (KodaX Space etc.) need to list providers + their models with context-window / reasoning info in popout UIs — but the pre-v0.7.43 path forced instantiation of each `KodaXProvider` class, which throws on missing API key. Static metadata was hidden behind runtime credentials, an architectural mismatch — that data is KodaX-maintained, not negotiated with the upstream. **Fix** (2-part): (1) Promote capability metadata (`contextWindow` / `maxOutputTokens` / `thinkingBudgetCap` / `supportsThinking` / full `KodaXModelDescriptor[]`) from per-Provider `class.config` field initializers UP to the existing `KODAX_PROVIDER_SNAPSHOTS` constant — Provider classes now derive their runtime `config` from the snapshot via `buildProviderConfig` (single source of truth, no drift risk; net −160 lines duplication / +30 lines metadata / byte-equivalent runtime behavior). (2) Add 9 new SDK exports reading directly from the snapshot (zero API keys touched): built-in `getProviderModelDescriptors` / `getModelCapabilities` / `listBuiltinModelCapabilities`; custom (from `~/.kodax/config.json#customProviders`) `getCustomProviderModelDescriptors` / `getCustomModelCapabilities` / `listCustomProviderModelCapabilities`; unified dispatchers `resolveProviderModelDescriptors` / `resolveModelCapabilities` / `listAllModelCapabilities`. New public type `KodaXModelCapabilities` exposed from `@kodax-ai/kodax/llm`. **`maxOutputTokens` rationale** (fix commit `c37b0a13`): the field IS reliable — it's the KodaX-side per-turn `max_tokens` request decision (bench-validated against kill-windows / decode-rate / cost-per-turn), NOT the upstream "theoretical maximum" (which is often inflated or absent — zhipu-coding / kimi-code / minimax-coding / ark-coding / deepseek `/v1/models` returns `{id, object, owned_by, created}` only). Embedders showing "expected output size" should use this value; theoretical ceilings should be looked up from the upstream provider's own docs. **Maintainer-probe scripts shipped**: `scripts/probe-upstream-model-metadata.mjs` (re-run periodically to detect upstream API improvements) + `scripts/probe-ark-tokens.mjs` (Ark-specific drill-down). **Tests**: `packages/llm/src/providers/model-capabilities.test.ts` 20/20 ✓ (no-API-key verification clears 6 env vars during assertion; snapshot drift guard asserts every `supportsThinking` provider declares `contextWindow` + every `models[]` entry is a descriptor object); full llm suite 304/304 ✓. **Bundle impact**: `dist/sdk-llm.d.ts` +1.2 kB (new types + symbols); `dist/sdk-llm.js` +400 bytes. **Architectural debt followup**: `KODAX_PROVIDER_SNAPSHOTS` still TS const compiled into bundle; capability data update path still needs `npm publish` + consumer `npm update`. FEATURE_198 (filed for v0.7.44) splits the snapshot to JSON + runtime loader for dist-patch-time updates (hot-update over network deferred to v0.7.46+). Docs: [`SDK_EMBEDDER_GUIDE.md §9`](public_docs/sdk/embedder-guide.md#9-querying-per-model-capabilities-without-api-keys).
2524
2737
  - **FEATURE_197 — Read-Only Markdown Agent Discovery: `discoverMarkdownAgents` SDK API (FEATURE_191 follow-up)** (1 commit, shipped 2026-05-24). KodaX Space (SDK 消费方) 2026-05-24 反馈:F191 `loadAgentsFromMarkdown` 触发 admission + 全局 registry 注册 side effect,他们想做 "agent picker" UI(用户 preview 已有 markdown agents 后再选择性激活),现有 loader 形态不匹配。`listConstructedAgentsWithSource()` 虽然技术上能 list 但是 `@internal` 标记的([`agent-resolver.ts:159-164`](packages/coding/src/construction/agent-resolver.ts#L159-L164) 明确写 "NOT yet a stable SDK surface; embedders SHOULD continue using `listConstructedAgents()`"),不能给 SDK consumer 用。F035 `discoverSkills(root?, opts?)` 是 pure read-only 形态,F191 没有对应的 read-only counterpart 是 SDK surface 设计 gap。**Fix**:抽 `parseMarkdownAgentFile(filePath)` shared helper(loader 和 discover 共用 parser,loader 行为 byte-identical),新增 `discoverMarkdownAgents(opts): Promise<{agents: DiscoveredMarkdownAgent[], failed: MarkdownLoadFailure[]}>` 公开 API:扫描同 two-tier path (user → project) → 返回 metadata `{name, description, source: 'markdown:user' | 'markdown:project', path, tools?, model?}`,**零 admission / 零 registration / 零全局 registry mutation**。Last-write-wins 与 loader parity(project 同名 shadow user)。Tools 字段返回 raw 名字不带 `builtin:` 前缀(discovery 暴露用户写的形态,ref-prefix 逻辑移到 loader 内 inline `.map(ref:)` 应用)。**Validation 边界**:discover 不验 admission(unknown tool ref / handoff cycle 都 surface),admission 仍在 `loadAgentsFromMarkdown` 兜底 — 与 F035 discoverSkills 不验 skill admission 形态对齐。**测试**:13 既有 F191 loader test 全过(parser 抽取无行为变化)+ 15 新 F197 unit test 覆盖 empty/missing-frontmatter/missing-name/missing-description/empty-body/project-shadows-user/tools-array/tools-csv/model-passthrough/admission-not-validated/loader-roundtrip-parity;**Read-only 硬契约**断言(`listConstructedAgents().length` discover 前后不变 + `resolveConstructedAgent(name)` discover 后仍 `undefined`)锁定 "discover 不能误注册" 边界。**Round-trip parity**断言 `discover.agents.length === loader.loaded` + 失败路径 set 相等 + 名字 set 相等 — 同 parser 共用保证 SDK consumer 用 discover preview 决定的 set 与最终 loader 激活的 set 一致。**Public surface**:`discoverMarkdownAgents` + `DiscoveredMarkdownAgent` + `DiscoverMarkdownAgentsResult` 从 `@kodax-ai/coding` 一路 reexport 到 `@kodax-ai/kodax` + `@kodax-ai/kodax/coding` 子路径。**Eval $0** — pure file-system + YAML parse, no LLM-facing change. 28/28 tests pass, tsc clean. 详见 [v0.7.43.md §FEATURE_197](docs/features/v0.7.43.md#feature_197-read-only-markdown-agent-discovery--discovermarkdownagents-sdk-apif191-follow-up).
2525
2738
  - **FEATURE_195 — Sidecar Verifier UI Silent Accept: Default-Hide Accept Verdict Evidence Entry + Transcript-Mode Opt-In** (1 commit `1b53150e`, shipped 2026-05-24). User 2026-05-24 实战 session 截图("你好 → 你好!" 对话)显示 sidecar verifier accept verdict 的 `reason` 文本以 `> [Evaluator] ...` event-item 渲染到 transcript,背离 FEATURE_184 (v0.7.42, ADR-030) "silent accept" 设计意图(accept verdict 应只走 session.jsonl + artifact,UI 端仅看 `[AMA Verifying]` spinner)。3-step pipeline 漏 silent 到 UI 层:(a) [`verifier-recorder-bridge.ts:89-104`](packages/coding/src/agent-runtime/middleware/sidecar-verifier/verifier-recorder-bridge.ts#L89) 历史 backward-compat 写 `role:'evaluator'` 入 recorder;(b) [`payload-builder.ts:249-298`](packages/coding/src/task-engine/_internal/managed-task/payload-builder.ts#L249) recorder 进 evidence.entries;(c) [`InkREPL.tsx:574-624`](packages/repl/src/ui/InkREPL.tsx#L574) `buildManagedTaskTranscriptItems` 无差别 render 全部 evidence.entries 为 event-item。**Fix**:单 commit REPL render filter — `shouldFilterSidecarAcceptEntry(entry, verifierLog)` helper + extend `buildManagedTaskTranscriptItems(result, options?: { verifierLog?: boolean })`;filter 规则 `role==='evaluator' AND signal==='COMPLETE' AND !verifierLog ⇒ filter`;revise/blocked verdict 因 signal 不是 `'COMPLETE'` 自然 fall-through。Default 读 `process.env.KODAX_VERIFIER_LOG === '1'` (复用 F184 Phase D.3 已有 env var);config 入口同时支持 `verifierLog: true` in `~/.kodax/config.json`。**数据层 0 改动**:`recorder.verdict` 仍写 session.jsonl + artifact —— replay / debug / scorecard / `kodax sessions` resume 全完整。**测试**:8 新 unit test 覆盖 4 verdict state (accept-no-userAnswer / accept-with-userAnswer / revise / blocked) × 2 mode (default / verifierLog=true)。**Root cause refinement during impl**:立项 doc 假设 H0_DIRECT trivial-chat `decidedByAssignmentId='evaluator'`,实际生产 `payload-builder.ts:218-219` 三元 `harness === 'H0_DIRECT' ? 'direct' : verdictStatus ? 'evaluator' : 'worker'` 让 H0_DIRECT 是 `direct`(最高优先级)——所有 fixture 已对齐生产路径用 `direct`。**Eval $0**:无 LLM-facing prompt change;UI render filter 是 deterministic 行为,unit test 覆盖 sufficient。**Concurrent-thread safety**:0 文件 overlap with F194 (改 `packages/{mcp,skills,tracing,session-lineage}`);atomic stage + commit + push 同 Bash 调用 per `feedback_concurrent_thread_git_race`。详见 [v0.7.43.md §FEATURE_195](docs/features/v0.7.43.md#feature_195-sidecar-verifier-ui-silent-accept--default-hide-accept-verdict-evidence-entry--transcript-mode-opt-in) + ADR-030 §F195/F196 cross-reference。
2526
2739
  - **FEATURE_196 — Sidecar Verifier Content-Aware Fire Gate: Action-Surface Detector + Conversational User-Intent Skip** (4 commits `10b8b290` → `c25ff99c` → `af7bc588` → this commit, shipped 2026-05-24). FEATURE_184 (v0.7.42, ADR-030) 在 Worker text-only termination 时无差别 fire sidecar verifier,包括 "你好" 这种零 action-surface trivial-chat 也跑 3-10s + LLM cost。F184 设计动机是抓 zhipu intent-vs-action floor(Worker 说 "明白,我用 todo_create..." 但没真调 tool),不是 trivial-chat 内容审查器;trivial chat 没有可 verify 的"声称完成"surface。F196 在 [`runner-driven.ts`](packages/coding/src/task-engine/runner-driven.ts) `composedStopHook` `!isIdleYieldTurn` 分支 `observer.sidecarStarted()` 之前加 deterministic 前置 gate `composeGateDecision(ctx, process.env)`,`fire===false` 直返 `extensionTurnCompleteHook(ctx)` 不进 sidecar;F184 fire 路径保持 byte-identical。**Gate 逻辑** (新模块 [`packages/coding/src/agent-runtime/middleware/sidecar-verifier/gate.ts`](packages/coding/src/agent-runtime/middleware/sidecar-verifier/gate.ts) ~213 LoC):(1) Layer 1 `detectActionSurface` — 看 last assistant message 有无 `tool_use` content block,有则 fire (action-surface);(2) Layer 2 `detectConversationalIntent` — greeting prefix regex (中英双语 + 通用 punctuation 👋 🙏) AND 长度 ≤ 20 codepoint AND 无 imperative verb (中文单字查/写/修/改/删/搜... + 中文多字 + 英文 imperative),三合取真则 skip (conversational);(3) escape hatch `KODAX_VERIFIER_ALWAYS=1` 强制 fire;(4) 默认 fire(保守失败 — F184 跑一遍 cost < 漏抓 zhipu floor)。`KODAX_VERIFIER_LOG=1` stderr `[sidecar-gate] {fire|skip}: <reason>` 复用 F195 env var。**测试**:23 unit (`gate.test.ts` — 6 actionSurface + 11 conversationalIntent + 6 composeGateDecision) + 3 integration (`runner-driven.test.ts` FEATURE_196 describe block — trivial-greeting skip / mutation-tool fire / imperative+zero-action fire) 全 pass。**Layer 2 eval — SHIP gate ALL EXCEEDED**(4 case × 5 canonical alias × 1 run = 60 panel cells + pilot 12 cells):(a) C1 greeting skip 5/5 alias **100%** (≥95% 立项门槛) / (b) C2 imperative fire 5/5 alias **100%** (≥95%) / (c) C3 long-message fire 5/5 alias **100%** (=100%) / (d) C4 no-greeting fire 5/5 alias **100%** (=100%) / (e) 5/5 alias meet (a)+(b) → **SHIP**。Eval cost **~$2 actual vs $10-15 budget** (under-spend ~8×) — gate logic deterministic(`composeGateDecision` is pure function),Layer 1 unit tests authoritative;Layer 2 scope 收窄到 tuple realism only("do real Worker LLM outputs across 5 provider families produce `KodaXContentBlock[]` shapes that `lastAssistantHasToolUse` detector handles?" + "do real model families respond to canonical user-message inputs with response patterns case categories assume?")。**3-judge audit 跳过** per EVAL_GUIDELINES.md §Layer 1 justification:gate decision per cell 是 `actualDecision === c.expectedDecision` 严格等值,无 LLM 歧义空间,3-judge majority 适用 LLM-judge 场景不适用 deterministic gate eval (raw text 抽查 spot-check 6 行已在 commit-3 message 记录)。**Eval drivers retained as permanent regression sweep**:`tests/feature-196-sidecar-content-gate.eval.ts` + `benchmark/datasets/feature-196-sidecar-content-gate/cases.ts` 入 repo;raw dumps 留 `<tmpdir>/kodax-eval-dumps/feature-196-sidecar-content-gate/` per `feedback_eval_dumps_stay_in_temp` 不入 repo;mkdirSync per flush survive Windows tmpdir race per `feedback_audit_dump_dir_vanishes`。**Behavior change for users**:trivial-chat (greeting + 零 tool call + ≤20 codepoint) 无 sidecar latency (省 3-10s tail + LLM cost);imperative + zero-action (zhipu intent-vs-action floor) 仍 fire 保 F184 contract;mutation + worker tool_use 仍 fire;`KODAX_VERIFIER_ALWAYS=1` env opt-back-in 强制 fire (debug / audit)。详见 [v0.7.43.md §FEATURE_196](docs/features/v0.7.43.md#feature_196-sidecar-verifier-content-aware-gate--action-surface-detector--conversational-user-intent-skip) + ADR-030 §F195/F196 cross-reference。