Skip to content

Commit 3481298

Browse files
author
goweft
committed
docs: WebView mode, app ingestion Steps 1+2, session log 2026-05-20b\n\nREADME:\n- Six agents named; mcp/ and webview/ in package layout\n- App ingestion quick-start: ingest <url> and browse <url>\n- DbC paragraph: MCPAgent/WebAgent + autonomy dial\n\nARCHITECTURE.md:\n- Verified-against commit df4372d\n- KindIngest and KindBrowse in request flow diagram\n- DBC table: MCPAgent and WebAgent rows; autonomy dial table\n\ndocs/concepts/app-ingestion.md:\n- Status: Steps 1+2 implemented, Step 3 research-phase\n- Dependency chain: Steps 1+2 SHIPPED with commit hashes\n\ndocs/session-2026-05-20b.md:\n- Block 4 ChatAgent, Step 1 MCP, Step 2 WebView\n- Toolchain resolution (chromedp dropped, Go 1.25.10 confirmed)\n- End state: 12 packages, 6 agents, 5 workspace types, 8 intent kinds
1 parent df4372d commit 3481298

4 files changed

Lines changed: 147 additions & 12 deletions

File tree

ARCHITECTURE.md

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# CAS Architecture
22

33
**Last updated:** 2026-05-19
4-
**Verified against:** commit `6b4ef8d`
4+
**Verified against:** commit `df4372d`
55

66
---
77

@@ -26,10 +26,12 @@ cmd/cas/main.go Entry point. Wires store → shell → TUI and starts
2626
internal/
2727
intent/ detect.go Zero-latency regex classifier. Fires before any LLM
2828
call. Maps a user message to a Kind and workspace type.
29-
agent/ agent.go Named sub-agents with per-agent contracts. Four agents:
29+
agent/ agent.go Named sub-agents with per-agent contracts. Six agents:
3030
GenerationAgent (create), EditAgent (edit), CombineAgent (combine),
31-
ChatAgent (chat). Shell delegates to agents; agents own every LLM call.
32-
Shell has no remaining LLM call sites — it only routes.
31+
ChatAgent (chat), MCPAgent (mcp tool calls), WebAgent (web actions).
32+
Shell delegates to agents; agents own every LLM call.
33+
mcp_agent.go MCPAgent: tool-call planning + execution, autonomy dial.
34+
web_agent.go WebAgent: web action planning (answer/navigate/extract), autonomy dial.
3335
contract/ contract.go Design by Contract enforcement. Pre/post/invariant
3436
checks on workspace operations. Fail-closed.
3537
workspace/ workspace.go Workspace type and lifecycle (create, update, close,
@@ -50,7 +52,11 @@ internal/
5052
*.lua. Sandboxed VM; no file I/O, no network.
5153
conductor/ conductor.go Behavioral learning. Observes interactions, builds
5254
~/.cas/profile.json, injects context into LLM prompts.
53-
mcp/ MCP integration layer (in progress).
55+
mcp/ client.go MCP client layer. Connect(), discoverTools(), Call(), Close().
56+
SSE transport via mark3labs/mcp-go.
57+
webview/ browser.go HTTP fetch + golang.org/x/net/html parser.
58+
NewSession(), Navigate(), Fetch(), FormatPageState().
59+
Extracts title, headings, links, body text; no browser runtime.
5460
5561
ui/ model.go Bubble Tea TUI model. Renders chat + workspace panels,
5662
handles keyboard, streams tokens into workspace view.
@@ -90,6 +96,18 @@ intent.Detect() ← regex only, no LLM call, no latency
9096
│ contract.CheckPostconditions() ← non-empty, ≤512 KB
9197
│ workspace.Create()
9298
99+
├─ KindIngest → MCPAgent (bound to workspace)
100+
│ contract.CheckPreconditions() ← instruction, connection, tools, autonomy
101+
│ llm.Complete() → tool selection
102+
│ contract.CheckPostconditions() ← tool name exists on server
103+
│ mcp.Connection.Call() (if autonomy ≠ suggest)
104+
105+
├─ KindBrowse → WebAgent (bound to workspace)
106+
│ contract.CheckPreconditions() ← instruction, session, page state, autonomy
107+
│ llm.Complete() → action selection (answer/navigate/extract)
108+
│ contract.CheckPostconditions() ← navigate_url valid if set
109+
│ webview.Session.Fetch() (if action = navigate)
110+
93111
└─ KindChat → ChatAgent
94112
contract.CheckPreconditions() ← message non-empty, history ≤ 20 turns
95113
llm.Stream()
@@ -134,10 +152,20 @@ Per-agent contract rules:
134152
| EditAgent | wsType valid, content non-empty, request non-empty | result non-empty, ≤ 512 KB, ≥ 10% of original |
135153
| CombineAgent | ≥ 2 sources, all sources non-empty | result non-empty, ≤ 512 KB |
136154
| ChatAgent | message non-empty, history ≤ 20 turns | reply guaranteed (fallback applied before check) |
155+
| MCPAgent | instruction non-empty, connection present, ≥1 tool, autonomy valid | selected tool name exists on server |
156+
| WebAgent | instruction non-empty, session present, page state present, autonomy valid | navigate_url (if set) is absolute |
137157

138158
The 10% truncation guard on EditAgent catches cases where the model returns
139159
only a fragment of the updated document instead of the full content.
140160

161+
**Autonomy dial** (MCPAgent and WebAgent):
162+
163+
| Value | Behaviour |
164+
|-----------|------------------------------------------------------------------|
165+
| `suggest` | LLM plans the action; tool/navigation not executed |
166+
| `confirm` | Action executed; result surfaced before continuing |
167+
| `run` | Action executed freely within workspace scope |
168+
141169
ChatAgent's postcondition is a guarantee rather than a hard check — if the
142170
model returns an empty reply, the fallback nudge is substituted before the
143171
postcondition runs, ensuring the contract is always satisfied.

README.md

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ contract.CheckPostconditions() // did the output meet requirements?
8585

8686
Contracts run in Go, external to the model. The model cannot modify, bypass, or reason about them. Any violation fails the operation — fail-closed always. Based on Bertrand Meyer's Design by Contract (1988).
8787

88-
Every LLM call is owned by a named agent (`GenerationAgent`, `EditAgent`, `CombineAgent`, `ChatAgent`). Contracts are frozen before the LLM call and checked again after. The shell delegates to agents and has no remaining LLM call sites — it only routes.
88+
Every LLM call is owned by a named agent (`GenerationAgent`, `EditAgent`, `CombineAgent`, `ChatAgent`, `MCPAgent`, `WebAgent`). Contracts are frozen before the LLM call and checked again after. The shell delegates to agents and has no remaining LLM call sites — it only routes.
89+
90+
`MCPAgent` and `WebAgent` operate under an **autonomy dial** (`suggest` / `confirm` / `run`) that governs whether actions are planned only, executed with confirmation, or executed freely within their workspace scope. The contract enforces that any tool or URL used exists on the bound server or page — the agent cannot reach outside its workspace.
8991

9092
### Three workspace types
9193

@@ -215,15 +217,18 @@ Full terminal editor via `charmbracelet/bubbles` textarea. All standard cursor m
215217
```
216218
internal/
217219
├── intent/ Zero-latency intent detection — regex, no LLM call
218-
├── agent/ Named sub-agents: GenerationAgent, EditAgent, CombineAgent, ChatAgent
219-
│ Each owns one category of LLM call with a frozen contract
220+
├── agent/ Six named sub-agents, each with a frozen contract
221+
│ GenerationAgent, EditAgent, CombineAgent, ChatAgent,
222+
│ MCPAgent (tool calls), WebAgent (web actions)
220223
│ Shell has no remaining LLM call sites — it only routes
221224
├── contract/ Design by Contract enforcement, fail-closed
222225
├── workspace/ Lifecycle: create, update, undo, close, restore
223226
├── shell/ Session manager: ProcessMessage, StreamMessage
224227
├── llm/ Ollama, Anthropic, Groq, OpenAI, OpenRouter — streaming/sync, model routing
225228
├── runner/ Code execution — sandboxed subprocess, timeout, env isolation
226229
├── plugin/ Lua plugin runtime — sandboxed gopher-lua VM
230+
├── mcp/ MCP client — connect, discover tools, call, close (SSE transport)
231+
├── webview/ HTTP fetch + HTML parser — title, headings, links, body text
227232
├── store/ Store interface, SQLiteStore (WAL), MemoryStore
228233
└── conductor/ Behavioral learning — observe, profile, user_context
229234
ui/ Bubble Tea TUI: split panel, tabs, streaming, inline edit
@@ -292,6 +297,28 @@ CAS_MODEL_CODE=anthropic/claude-3-5-haiku ./cas
292297
./cas --providers
293298
```
294299

300+
### Ingest an MCP server
301+
302+
```bash
303+
# In chat: connects and opens a workspace with the server's tools listed
304+
ingest https://mcp.linear.app/sse
305+
306+
# Then ask the agent to use a tool:
307+
# "list my open issues" → MCPAgent reasons, selects tool, calls it
308+
```
309+
310+
### Browse a web page
311+
312+
```bash
313+
# In chat: fetches the page and opens a workspace with its content
314+
browse https://golang.org
315+
316+
# Then ask the agent to work with it:
317+
# "summarise the main sections"
318+
# "navigate to https://golang.org/doc/install"
319+
# "extract all links"
320+
```
321+
295322
### Flags
296323

297324
```

docs/concepts/app-ingestion.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# App Ingestion
22

3-
**Status:** Concept. Depends on sub-agent decomposition (planned, not yet designed).
3+
**Status:** Steps 1 and 2 implemented. Step 3 (native app) research-phase.
44

55
---
66

@@ -184,16 +184,16 @@ Prerequisite ──────── sub-agent decomposition with Heddle contra
184184
Not yet designed in detail. Load-bearing for what
185185
follows — every ingested workspace binds a sub-agent.
186186
187-
Step 1 ────────────── API-mode ingestion
187+
Step 1 ────────────── API-mode ingestion ✓ SHIPPED (784e94e)
188188
· Workspace surface (operations + state + sub-agent)
189189
· Autonomy dial
190190
· Scoped memory with intent tags
191191
192-
Step 2 ────────────── WebView-mode ingestion
192+
Step 2 ────────────── WebView-mode ingestion ✓ SHIPPED (df4372d)
193193
· Embedded browser runtime
194194
· Authoritative DOM access
195195
196-
Step 3 ────────────── Native app window adoption
196+
Step 3 ────────────── Native app window adoption (research-phase)
197197
· Platform-specific (research-heavy)
198198
```
199199

docs/session-2026-05-20b.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Session Log — 2026-05-20 (continued)
2+
3+
## What we worked on
4+
5+
### Block 4: ChatAgent
6+
7+
**ChatAgent** (`6b4ef8d`)
8+
Final agent in the decomposition. Owns all KindChat LLM calls.
9+
- Preconditions: message non-empty, history ≤ 20 turns
10+
- Postcondition: reply guaranteed — fallback nudge substituted if model
11+
returns empty, so the contract is always satisfied rather than failing
12+
- `contextSuffix()` helper removed from shell (chat-agent owns it internally)
13+
- Shell has zero remaining LLM call sites — it only routes
14+
15+
Shell updated: `handleChat`/`streamChat``chatAgent.Chat`/`Stream`.
16+
Tests: +2 contract violation tests (empty message, excessive history).
17+
Docs: README and ARCHITECTURE updated — all four agents named, shell-only-routes.
18+
19+
### App ingestion Step 1: MCP server as workspace
20+
21+
**MCP client + MCPAgent + KindIngest** (`784e94e`)
22+
- `internal/mcp/client.go`: Connect(), discoverTools(), Call(), Close()
23+
SSE transport via mark3labs/mcp-go v0.54.0
24+
- `internal/agent/mcp_agent.go`: MCPAgent with three-level autonomy dial
25+
(suggest/confirm/run). LLM selects tool + args from server tool summary;
26+
JSON response parsed to MCPToolCall; plain-text fallback if no tool selected.
27+
Contract: instruction non-empty, connection present, ≥1 tool, autonomy valid;
28+
post: selected tool name must exist on the server
29+
- KindIngest in intent: `ingest <url>`, `connect (to) <url>`,
30+
`add (mcp) server/source <url>`
31+
- Shell: handleIngest → Connect → materialize 'mcp' workspace → bind connection;
32+
HandleMCPAction, CloseMCPWorkspace exposed for UI layer
33+
- DefaultWorkspaceContract accepts 'mcp' type
34+
- Tests: 5 MCPAgent contract tests, 6+4 ingest intent tests
35+
36+
### App ingestion Step 2: WebView mode
37+
38+
**WebView + WebAgent + KindBrowse** (`df4372d`)
39+
- `internal/webview/browser.go`: stdlib HTTP + golang.org/x/net/html
40+
NewSession(), Navigate(), Fetch(), FormatPageState(), ParseForTest()
41+
Parser: title, headings (h1–h3), links (top 30, absolute URLs), body text
42+
Script/style excluded; body truncated to 4 KB
43+
- `internal/agent/web_agent.go`: WebAgent with WebAction types
44+
(answer/navigate/extract), same autonomy dial as MCPAgent
45+
LLM selects action from page context summary; JSON response or plain-text fallback
46+
Contract: instruction, session, page state, autonomy; post: navigate_url valid
47+
- KindBrowse in intent: browse/open/scrape/fetch/read/summarise/summarize/
48+
go to + URL
49+
- Shell: handleBrowse, HandleWebAction (updates page state on navigate),
50+
CloseWebWorkspace
51+
- DefaultWorkspaceContract accepts 'web' type
52+
- Tests: 7 webview parser tests, 4 WebAgent contract tests,
53+
8+5 browse intent tests
54+
55+
**Toolchain resolution** (also in df4372d)
56+
chromedp (Go 1.26 requirement) dropped; stdlib approach used instead.
57+
Build verified against Go 1.25.10 at /home/gostev/go-install.
58+
go.mod pinned to 1.25.5 (mcp-go requirement). CI unchanged (go-version: '1.25').
59+
60+
## End state
61+
62+
- **HEAD:** `df4372d`
63+
- **Packages:** 12 (added internal/mcp, internal/webview)
64+
- **Agents:** GenerationAgent, EditAgent, CombineAgent, ChatAgent,
65+
MCPAgent, WebAgent
66+
- **Workspace types:** document, code, list, mcp, web
67+
- **Intent kinds:** create, edit, close, run, combine, chat, ingest, browse
68+
- **Tests:** all passing across all 12 packages
69+
- **Go toolchain:** 1.25.10 (local), 1.25.5 (go.mod min), 1.25 (CI)
70+
71+
## What's next
72+
73+
Per concept doc dependency chain:
74+
- Step 3 (native app window adoption) is research-phase — X11/Wayland,
75+
platform-specific, no clear timeline
76+
- Immediate: update concept doc to mark Steps 1 and 2 as implemented
77+
- Blog: post 04 still queued for dev.to publish
78+
- Sub-agent coordination: if two ingested workspaces need to act together
79+
(e.g. "take this Linear issue, file a GitHub PR"), the orchestration
80+
pattern is not yet designed

0 commit comments

Comments
 (0)