decide the dogfood agent model (D-83)
Records D-83 answering Gap 5 of docs/self-analysis.md: clide commits to both "Claude inside clide" models, with the clide-HOSTED stream-json session (D-77/D-78) as the PRIMARY dogfood target — the process clide spawns, hence the one Epic B (T-214) bootstraps (CLIDE_SOCK/CLIDE_WORKSPACE + PATH + context note + Bash(clide *) allow rule). The EXTERNAL CLI driver (D-68) stays a first-class but SECONDARY, best-effort integration: manual install (T-212), no promise to observe its non-clide tool use. Scopes the D-6 parity contract (Epic C / T-218) to clide's own surfaces reflected through the CLI in both directions; an external agent's side-channel reads/tests/git are explicitly out of parity scope. Closes T-224 (under T-208 "Give Claude hands"). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -53,3 +53,8 @@ INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by,
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-213', 'status', 'in_progress', 'done', NULL, '2026-06-03 09:00:37', '2026-06-03 09:00:37', '2026-06-03 09:00:37', NULL, '7df53985fc88d02f9087ccfcf78770ae', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-210', 'status', 'in_progress', 'done', NULL, '2026-06-03 09:00:37', '2026-06-03 09:00:37', '2026-06-03 09:00:37', NULL, '84dd4f5fa45cb78da9a0b11c73fb149b', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-211', 'status', 'in_progress', 'done', NULL, '2026-06-03 09:00:37', '2026-06-03 09:00:37', '2026-06-03 09:00:37', NULL, 'aa86077555916ee351369e23a6ca155b', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-224', 'status', 'backlog', 'in_progress', NULL, '2026-06-03 09:02:26', '2026-06-03 09:02:26', '2026-06-03 09:02:26', NULL, 'e3b4e65b26974834bbb073ddebf667f7', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-224', 'description', 'Gap 5 from self-analysis.md — foundational. Two distinct ''Claude inside clide'' stories with different gaps: (A) the clide-HOSTED stream-json session (D-77/D-78) — the user''s primary Claude pane, which itself needs `clide` on PATH to drive the surrounding IDE; (B) an EXTERNAL agent (e.g. a Claude Code harness, TERM_PROGRAM=zed as observed) driving via `clide ...` IPC, which clide cannot fully observe because plain file reads / `make test` / `git` bypass clide. Decide the intended model — hosted, external, or both — and record it under governance/ (claim via `pql decisions claim`). Gates how Epic B bootstraps and how Epic C frames observability.', 'Gap 5 from self-analysis.md — foundational. Two distinct ''Claude inside clide'' stories with different gaps: (A) the clide-HOSTED stream-json session (D-77/D-78) — the user''s primary Claude pane, which itself needs `clide` on PATH to drive the surrounding IDE; (B) an EXTERNAL agent (e.g. a Claude Code harness, TERM_PROGRAM=zed as observed) driving via `clide ...` IPC, which clide cannot fully observe because plain file reads / `make test` / `git` bypass clide. Decide the intended model — hosted, external, or both — and record it under governance/ (claim via `pql decisions claim`). Gates how Epic B bootstraps and how Epic C frames observability.
|
||||
|
||||
Resolved (2026-06-03): recorded as D-83. Decision — clide commits to BOTH agent models with the clide-HOSTED stream-json session (D-77/D-78) as the PRIMARY dogfood target (the one clide spawns, so the one Epic B/T-214 bootstraps: CLIDE_SOCK/CLIDE_WORKSPACE + PATH + context note + Bash(clide *) allow rule), and the EXTERNAL CLI driver (D-68) as a first-class but SECONDARY, best-effort integration (manual install via T-212; no promise to observe its non-clide tool use). Epic C/T-218 parity is scoped to clide''s own surfaces reflected through the CLI in both directions; an external agent''s side-channel reads/tests/git are out of parity scope.', NULL, '2026-06-03 09:05:48', '2026-06-03 09:05:48', '2026-06-03 09:05:48', NULL, 'c6b6237b6f3d7f072a4b9b0a4cc30bc9', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-224', 'status', 'in_progress', 'done', NULL, '2026-06-03 09:05:50', '2026-06-03 09:05:50', '2026-06-03 09:05:50', NULL, 'e6b1c1f085d251762e927b9ea9d20076', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
|
||||
@@ -82,3 +82,6 @@ INSERT INTO tickets (id, type, parent_id, title, description, status, priority,
|
||||
INSERT INTO tickets (id, type, parent_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-213', 'task', 'T-209', 'Regression test: clideVersion matches pubspec version', 'Gap 6 version-drift guard. clideVersion in lib/src/build_info.g.dart (generated by gen-build-info) currently matches pubspec.yaml `version:` (both 2.1.0). Add a test asserting they stay equal so an agent keying off `clide version` is never misled.', 'done', 'low', NULL, NULL, NULL, '2026-06-02 18:13:52', '2026-06-03 09:00:37', NULL, '1cc6925922c30c6f7e1dc9ee356de8e3', 1) ON CONFLICT(id) DO UPDATE SET type=excluded.type, parent_id=excluded.parent_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (id, type, parent_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-211', 'task', 'T-209', 'install delivers the C client to PATH on macOS and Linux', 'Fix `make install` so $(INSTALL_DIR)/clide (default ~/.local/bin/clide) IS the compiled C client, not the Flutter GUI binary. Today Makefile:200 symlinks the GUI bundle runner on both platforms. Acceptance: after `make install`, `which clide` resolves and `clide ping` returns {"pong":true} against a running instance on macOS and Linux. Blocked by ''Build the C client by default''.', 'done', 'high', NULL, NULL, NULL, '2026-06-02 18:13:52', '2026-06-03 09:00:37', NULL, '2e1f0a48393ff4f04079124fd2a1f579', 1) ON CONFLICT(id) DO UPDATE SET type=excluded.type, parent_id=excluded.parent_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (id, type, parent_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-210', 'task', 'T-209', 'Build the C clide client by default', 'Make the `clide-cli` target (Makefile:284) a dependency of `build` (Makefile:169) and `install` (Makefile:195) so the C client is always produced. Today it builds only via the explicit, non-default `make clide-cli`. Acceptance: a plain `make build` / `make install` produces the C client binary for the current OS.', 'done', 'high', NULL, NULL, NULL, '2026-06-02 18:13:52', '2026-06-03 09:00:37', NULL, '738656b25288166130ca516a88b94784', 1) ON CONFLICT(id) DO UPDATE SET type=excluded.type, parent_id=excluded.parent_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (id, type, parent_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-224', 'task', 'T-208', 'Decide the dogfood agent model (governance Q/D record)', 'Gap 5 from self-analysis.md — foundational. Two distinct ''Claude inside clide'' stories with different gaps: (A) the clide-HOSTED stream-json session (D-77/D-78) — the user''s primary Claude pane, which itself needs `clide` on PATH to drive the surrounding IDE; (B) an EXTERNAL agent (e.g. a Claude Code harness, TERM_PROGRAM=zed as observed) driving via `clide ...` IPC, which clide cannot fully observe because plain file reads / `make test` / `git` bypass clide. Decide the intended model — hosted, external, or both — and record it under governance/ (claim via `pql decisions claim`). Gates how Epic B bootstraps and how Epic C frames observability.
|
||||
|
||||
Resolved (2026-06-03): recorded as D-83. Decision — clide commits to BOTH agent models with the clide-HOSTED stream-json session (D-77/D-78) as the PRIMARY dogfood target (the one clide spawns, so the one Epic B/T-214 bootstraps: CLIDE_SOCK/CLIDE_WORKSPACE + PATH + context note + Bash(clide *) allow rule), and the EXTERNAL CLI driver (D-68) as a first-class but SECONDARY, best-effort integration (manual install via T-212; no promise to observe its non-clide tool use). Epic C/T-218 parity is scoped to clide''s own surfaces reflected through the CLI in both directions; an external agent''s side-channel reads/tests/git are out of parity scope.', 'done', 'high', NULL, NULL, 'D-77', '2026-06-02 18:13:52', '2026-06-03 09:05:50', NULL, '8ba80265666e3103ea82c02fdf48e632', 1) ON CONFLICT(id) DO UPDATE SET type=excluded.type, parent_id=excluded.parent_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
|
||||
@@ -124,6 +124,7 @@ You might also want, project-permitting:
|
||||
- [D-80: `files.read` allows trusted Claude config roots beyond the workspace](decisions/architecture.md#d-80-filesread-allows-trusted-claude-config-roots-beyond-the-workspace) — _architecture_
|
||||
- [D-81: Right-pane reader load is driven by a retained `ReaderNav`, not per-view state or bus retention](decisions/architecture.md#d-81-right-pane-reader-load-is-driven-by-a-retained-readernav-not-per-view-state-or-bus-retention) — _architecture_
|
||||
- [D-82: Keymap sequences are space-separated; matching is a reusable matcher consumed at the interception point](decisions/architecture.md#d-82-keymap-sequences-are-space-separated-matching-is-a-reusable-matcher-consumed-at-the-interception-point) — _architecture_
|
||||
- [D-83: Dogfood agent model — hosted stream-json session primary, external CLI driver secondary](decisions/architecture.md#d-83-dogfood-agent-model--hosted-stream-json-session-primary-external-cli-driver-secondary) — _architecture_
|
||||
|
||||
## Open questions
|
||||
|
||||
|
||||
@@ -390,3 +390,15 @@ Core, rendering, IPC, kernel, panel manager.
|
||||
- **Raised by:** 2026-06-01 — scoping the Vim preset for a Vim-power-user demo; the user weighed `,`/`;`/`>` separators and flagged the escaping problem, which made space the collision-free choice.
|
||||
|
||||
---
|
||||
|
||||
### D-83: Dogfood agent model — hosted stream-json session primary, external CLI driver secondary
|
||||
- **Date:** 2026-06-03
|
||||
- **Status:** accepted
|
||||
- **Decision:** There are two distinct "Claude inside clide" agents, and clide commits to **both** with an explicit primary. **(A) The clide-hosted stream-json session is the primary dogfood target.** Per [D-77](#d-77-drive-claude-via-the-stream-json-control-protocol-teams-become-a-clide-owned-coordination-layer)/[D-78](#d-78-claude-permissionprompt-transport-is-the-stdio-control-channel) clide *spawns* the Claude process, so it owns that child's environment — this is the agent clide can fully **bootstrap** (inject `CLIDE_SOCK`/`CLIDE_WORKSPACE`, guarantee `clide` on its PATH, inject a context note, seed a `Bash(clide *)` allow rule — Epic B / T-214) and the agent the rest of the product is built around. **(B) An external Claude Code harness driving via `clide …` is a first-class but secondary, best-effort integration** — the same surface [D-68](#d-68-dual-integration-surface--bash-cli-primary-mcp-secondary) already opens to "human shell use, scripts, and external editor integrations." clide serves the per-workspace socket ([D-70](#d-70-ipc-socket-path-is-per-workspace-deterministic)) to anyone who can reach it and offers a manual install affordance (T-212), but makes **no promise to observe an external agent's non-`clide` tool use** (plain file reads, `make test`, `git`) — those bypass the socket and are outside clide's view by construction.
|
||||
- **Parity scope (how this frames Epic C):** the [D-6](#d-6-cli-and-event-surface-contract) "agent sees what the user sees" contract is scoped to **clide's own surfaces, reflected through the CLI in both directions** — the live UI panes/buffers/active-file become readable via `pane list` / `editor active` / `clide status` (T-219/T-220/T-221), and an external agent's `clide …` mutations are observable on the event bus. An external agent's side-channel tool use (reads/tests/git issued in its own shell) is **explicitly out of parity scope**: clide reflects what flows through clide, not what an unowned process does elsewhere.
|
||||
- **Rationale:** (a) clide can only *bootstrap* a process whose launch it controls — env, PATH, permission rules, and context injection are all things you set when you `spawn`, not things you can push into a shell you didn't start; so the hosted session (A) is where Epic B's leverage actually exists, which makes it the right primary. (b) Naming (A) primary aligns the dogfood target with the product's main interaction surface (the native Claude pane, D-77). (c) Refusing to drop (B) keeps faith with D-68 (the CLI is deliberately an external-integration surface) and with reality — the self-analysis probe and this very initiative are being driven by an external harness; declaring it out of scope would make clide unable to describe its own development. (d) Scoping parity to "what flows through clide" keeps the contract **honest and testable**: clide can verify it mirrors its own UI state, but cannot truthfully promise to observe tool calls that never touch its socket.
|
||||
- **Cost / risk:** Two supported models means two bootstrap stories. Mitigated by the asymmetry being the point — (A) gets the full automated bootstrap; (B) gets a documented manual path (install `clide`, the deterministic socket resolves the rest) and best-effort observability, not a second full implementation. The honest limit on (B) — clide is blind to an external agent's non-`clide` work — is a stated boundary, not a bug to chase; an external agent that wants clide to see an action runs it *through* `clide …`.
|
||||
- **Cross-reference:** answers Gap 5 of [`docs/self-analysis.md`](../../docs/self-analysis.md); gates [D-77](#d-77-drive-claude-via-the-stream-json-control-protocol-teams-become-a-clide-owned-coordination-layer)/[D-78](#d-78-claude-permissionprompt-transport-is-the-stdio-control-channel) (the hosted session this names primary), [D-68](#d-68-dual-integration-surface--bash-cli-primary-mcp-secondary) (the external CLI surface kept as secondary), [D-6](#d-6-cli-and-event-surface-contract) (parity scoped here), [D-70](#d-70-ipc-socket-path-is-per-workspace-deterministic) (the socket an external agent reaches). Frames Epic B ([T-214](#)) bootstrap target and Epic C ([T-218](#)) observability scope under initiative [T-208](#) "Give Claude hands". Implemented/decided by T-224.
|
||||
- **Raised by:** 2026-06-03 — T-224, processing the self-analysis.md dogfood probe from inside clide. The probe itself ran as an external harness (B) while the product is built around the hosted session (A); user chose "both, primary = hosted (A)" so Epic B optimizes the bootstrap clide can actually control while keeping the external driver a supported, best-effort integration.
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user