kcode-dev-tools-chatend 0.1.2

Chatend projection for Kennedy's managed development tools
Documentation
# Development Tools Chatend Adapter

`kcode-dev-tools-chatend` projects managed-development source state and freeform-write captures into a `kcode_session_history::Session`. It re-exports `ManagedSourceKind` and `SourceSnapshot`. It does not authorize or execute development tools; the caller remains responsible for principal authority, tool ordering, and handling backend results.

## Source snapshots

```rust
pub fn apply_snapshot(
    session: &mut Session,
    recorded_at: &str,
    snapshot: SourceSnapshot,
) -> anyhow::Result<BoxId>;

pub fn source_box_id(
    session: &Session,
    kind: ManagedSourceKind,
    name: &str,
) -> Option<BoxId>;
```

After a successful managed-source operation returns a complete `SourceSnapshot`, call `apply_snapshot`. It durably creates or revises the active stable Chatend source box for that exact kind and project name, preserving its `BoxId` when revising it; Rust libraries, Web libraries, and Rust binaries use separate tool instances. `source_box_id` finds that active, non-retired box by exact logical name.

## Freeform writes

```rust
pub fn prepare_freeform_write(
    session: &Session,
    tool_name: &str,
    arguments: &serde_json::Value,
) -> anyhow::Result<Option<FreeformWrite>>;

pub fn decode_freeform_write(
    tool_name: &str,
    arguments: &serde_json::Value,
) -> anyhow::Result<Option<FreeformWrite>>;
```

`decode_freeform_write` performs the same strict parsing without consulting
Session History. A box-free caller must separately prove that the named source
is open in its own current-state projection.

Call `prepare_freeform_write` for an incoming managed Rust-library, Web-library, or Rust-binary freeform-write call. Unrelated tool names return `Ok(None)` without validating arguments. A recognized call must contain exactly the string fields `name`, `path`, and `updateDescription`; surrounding whitespace is trimmed, all must be nonempty, their maximum lengths are 255, 4096, and 4000 characters respectively, and `path` and `updateDescription` must each be one line. The named source must already have an active box in this session, normally installed from a prior successful open snapshot, or preparation fails.

`FreeformWrite` is opaque and provides:

```rust
pub fn acknowledgement(&self) -> String;
pub fn kind(&self) -> ManagedSourceKind;
pub fn name(&self) -> &str;
pub fn preview_tool(&self) -> &'static str;
pub fn write_tool(&self) -> &'static str;
pub fn source_box_id(&self, session: &Session) -> anyhow::Result<BoxId>;
pub fn result_record(&self, ok: bool, result: &str) -> serde_json::Value;

pub fn capture(
    &self,
    session: &mut Session,
    recorded_at: &str,
    invocation_box_id: BoxId,
    contents: String,
) -> anyhow::Result<serde_json::Value>;

pub fn capture_subagent(
    &self,
    session: &mut Session,
    recorded_at: &str,
    contents: String,
) -> anyhow::Result<serde_json::Value>;
```

The caller should prepare the request, run the non-mutating `preview_tool`, issue `acknowledgement`, collect only the complete provider file, revalidate the still-open target with the request's `source_box_id`, then use exactly one capture method. The returned JSON is the argument object for `write_tool`; capture does not execute or authorize that tool. `result_record` only builds the later application-note value and does not persist it.

Both capture paths preserve the UTF-8 contents except that one final `\n` is appended when missing. Normalized contents must not exceed 4 MiB (4,194,304 bytes); oversize input is rejected before session mutation. `capture` replaces the canonical content of `invocation_box_id` with the captured source and then summarizes that box. The caller must supply the trusted box for the exact authorized invocation: this crate does not establish ownership or suitability of an arbitrary `BoxId`. `capture_subagent` instead records a durable `subagent_freeform_write_output` note containing the source. Both return normalized backend arguments containing `name`, `path`, and `contents`.

Session writes are persistent effects, not transactions. In particular, `capture` updates the invocation box before attempting its summary, so a later error can leave captured content installed without a summary or returned backend arguments. On any mutation error, inspect or reload session state before retrying; do not assume that `Err` means no effect. Preparation and lookup are non-mutating. No operation here publishes source, stores binary output in Kmap, resolves Kweb objects, or grants deployment or messaging authority.