Commit Graph

5 Commits

Author SHA1 Message Date
Tianyi Cui
66c36e7325 feat: add canonical typed tool outputs 2026-07-21 03:22:14 +08:00
Tianyi Cui
148046b9c8 docs: rebalance prose cleanup and add trimming skill 2026-07-13 23:27:00 +08:00
Tianyi Cui
75838e10b5 docs: trim generated prose 2026-07-12 03:36:43 +08:00
imccyu
3e9527278a fix(tool-cordis): gate façade services on inject, and make tools.get read-only
Two review findings (#220) on the sandbox context façade:

- Undeclared services were reachable: the façade resolved any live global via
  ctx.get(name), so ctx.bash worked without inject: ['bash']. A cross-mount
  consumer could then depend on a provider cordis never saw — unmounting the
  provider would neither park the consumer nor unwind its registered tools,
  leaving a model-visible tool that fails only at execution. The façade now
  reads ctx.fiber.inject and refuses any service the mount did not declare
  (with a teaching error naming the inject fix), so the dependency is always
  visible to cordis and its activation/unload semantics bind.

- ctx.tools.get returned the live ToolDefinition, including execute — mount
  code could call another tool directly and bypass ToolRegistry.execute and
  its pre/post-execute hooks and accounting. get now returns the same
  read-only name/description/parameters view as schemas(), never an invocable.

Adds inject-gate and schema-view regression cases to sandbox-context.spec.ts
(undeclared property/get denied, declared allowed, the cross-mount zombie-tool
scenario refused at call time, get exposes no execute). Package stays at
per-file 100% coverage. RFC, mount description, and tool-catalog updated.
2026-07-09 13:57:03 +08:00
imccyu
1b1ba96d4f fix(tool-cordis): replace the pass-through ctx proxy with a whitelist façade
Review finding (#220): the guarded proxy only special-cased ctx.tools, so
mount code could reach an UNGUARDED context through ctx.root, ctx.extend(), or
a service instance's .ctx, then ctx.root.tools.register({…}) to bypass the
marker check and host-realm normalization — a raw vm-realm result would later
error a real agent turn at the session-log plainness check.

The sandbox ctx is now a whitelist façade, not a pass-through proxy: it exposes
only what a mount needs — tools.register (marker-guarded), on/once, provide, the
timer helpers, and injected services resolved through a guarded get — and denies
every framework-plumbing member (root, parent, fiber, reflect, registry, extend,
isolate, intercept, plugin, set, mixin, …) with a teaching error. Injected
services are wrapped so a method returning a Context is rejected on the way back
(the .ctx escape), closing the one indirect leak. There is no context-valued
member left to reach; cross-mount provide/inject is untouched (the plugin's own
inject and the fiber's pending/active gating are unchanged). ctx.plugin (child
plugins) and ctx.set are denied by design; ctx.effect is deferred (FIXME).

Adds tests/sandbox-context.spec.ts covering the escape class (root/extend/fiber/
plugin/set/… denied, the classic root.tools.register bypass, the .ctx escape,
read-only writes) plus the async-service and symbol/in-operator paths for 100%
coverage. RFC/README/tool-catalog/config-catalog updated; api-catalog.ts
regenerated (also picks up the codeRuntime service that entered on the master
merge and was left stale).
2026-07-09 13:57:03 +08:00