-
Notifications
You must be signed in to change notification settings - Fork 0
how to contribute patterns and conventions
Coding rules that keep Foundry honest when agents, git, and the UI all touch the same run.
Comments state the constraint behind a decision, not a restatement of the next line. Load-bearing examples live next to the droid protocol quirks, earned-success defaults, and IPC structured-clone handling. Match that style; do not narrate obvious code.
UI strings, logs, and commits in this app tree stay plain text. Prefer a comma or parenthesis over an em dash in prose and UI strings.
Anything sent over Electron IPC must be plain data. src/renderer/api.ts routes arguments through plain() so a wrapped object cannot fail to serialize (that failure surfaces only as a button that appears to do nothing). The full capability list is src/shared/ipc-contract.ts.
- A handler that can reject must catch and show the error. Silence reads as a bug.
- Unreported model usage displays as unreported, not zero.
- Unknown gate names fail the phase.
- A policy-blocked model degrades with a warning instead of killing the session.
-
A phase is born
fail. Flip to success only on clean exit (+ envelope + gates for agent phases). - Code owns sequencing, retries, and acceptance. Agents never decide success.
- Corrections re-prompt the same live session. Envelope retries and gate retries have separate budgets.
-
Gates return evidence, one
GateCheckper examined item. - Write boundaries are enforced in code after the call by diffing git status; unauthorized writes are reverted.
-
finish()settles status, notification, banner, andoutcome_detailtogether. - Runs use a git worktree; the base checkout is never mutated by the engine.
Five agents and seven pipelines ship as builtins. User-edited copies live in the JSON store. Changing the builtin list must never clobber a user's copy.
Per-phase cost, duration, and model are derived from events in src/renderer/derive.ts, not denormalized onto phases columns. Do not add a total_tokens column to phases to "simplify" the UI.
Encoded in src/main/droid/protocol.ts and enforced by tests/fake-droid.ts:
- Frames need a
typediscriminator plus Factory API/protocol version fields. Plain JSON-RPC is rejected with-32700. - Request
idmust be a string. Numeric ids are rejected the same way. - Session settings (
modelId, reasoning effort, autonomy) are flat params ondroid.update_session_settings. Nested undersettingsthey are silently ignored.
Also: add_user_message takes params.text (not message) and returns immediately; the turn ends with agent_turn_completed. tool_call is re-emitted per toolUseId as arguments stream, so the client folds them into one span.
Tests use real git repositories in mkdtemp directories and a scripted droid stub. No network, no model in the loop. New engine behaviour needs a test in that style. See Testing.
Do not import from, execute, or link against .claude/. Do not add Python to apps/desktop/. Read the skill to understand a concept, then implement it in TypeScript.
Overview
Snapshot and history
How to contribute
Apps
Systems
Features
Primitives
Background and security
Reference