-
Notifications
You must be signed in to change notification settings - Fork 0
fun facts
Odd, load-bearing, or easy-to-miss details about Foundry and the SSSF skill. For system shape see Architecture; for tables see By the numbers; for timeline see Lore.
src/main/droid/protocol.ts encodes behaviour observed against the real CLI, not the docs. Three details will break a naive JSON-RPC client every time:
- Frames need a
typediscriminator plusfactoryApiVersion/factoryProtocolVersion. A plain JSON-RPC frame is rejected with-32700. - Request
idmust be a string. A number is rejected the same way, so "JSON-RPC allows numeric ids" is the wrong assumption here. - Session settings (
modelId, reasoning effort, autonomy) are flat params ondroid.update_session_settings. Nest them undersettingsand they are silently ignored (no error, no model switch, just quiet wrongness).
Also: add_user_message takes params.text (not message) and returns immediately; the turn ends on an agent_turn_completed notification. tool_call is re-emitted per toolUseId as arguments stream, so the client must fold multiple frames into one span.
tests/fake-droid.ts reproduces these quirks on purpose. "Simplifying" the client toward textbook JSON-RPC is how you get a green unit suite and a dead real session.
Every phase row starts life as a failure. It flips to success only on a clean exit, and for agent phases only after a parsed envelope and green gates. The same doctrine lives in SSSF and Foundry (tracer.ts and executor.ts both spell it out).
That sounds pessimistic until you watch a crash mid-phase: the default already matches reality, and partial success never paints a green lane by accident. Run acceptance is a second question, settled only in finish(), because a test phase that correctly reported a red suite did its job and still must not mark the run accepted.
Five builtin agents: planner, builder, scout, reviewer, documenter. Running the suite is a code phase (command: { ref: 'test' } or equivalent), not a sixth personality with a system prompt.
The lore goes back to SSSF hard rule 8: if you can write the invocation down, it belongs in code. Agents rediscovering your test runner burn context to learn what a subprocess already knows, and they charge for it every run. Failures still feed back to the builder as envelopes; the repair loop is the same without renting a model to run arithmetic.
SSSF warned operators that type, ## Report example, and output_type= must stay aligned by hand, and that drift burns correction rounds. Foundry's envelopes.ts opens with the same problem statement and then removes the footgun:
The synced-triad problem (type ↔ prompt example ↔ call site) is solved by construction here:
exampleForderives the JSON example the agent is shown from the same zod schema the answer is parsed against.
Builtin agent prompts intentionally do not embed the report example. The schema generates it at render time and appends it, so the shape shown and the shape parsed cannot diverge without a deliberate schema change. Custom agent fields compile into schema and example on the same path.
On 2026-08-06 the tallest TypeScript files were:
| File | ~Lines |
|---|---|
executor.ts |
841 |
tracer.ts |
825 |
client.ts |
465 |
ipc.ts |
427 |
The run loop, the only SQLite writer, the droid session, and the full IPC surface: that is the factory. The renderer is larger in aggregate (~3.7k LOC) but spread across many screens and components. If you are hunting for "where does Foundry actually decide things?", start with those four files, not the waterfall chrome.
Public history on the ancestor line records the 2026-08-02 skill landing with commit subject 🚀 (nothing else). Foundry's 2026-08-06 commit is the opposite register: a multi-paragraph message that restates the doctrines (code owns the loop, phase born fail, live-session corrections) before listing engine, droid, trace, and renderer.
One era opened with an emoji. The next era's house style, written into AGENTS.md, forbids emoji in source and UI copy. Both artefacts still share the same control-plane ideas.
-
No TODOs in
apps/desktop/srcon the snapshot date. The unfinished work is product scope (seePLAN.md), not scattered// TODOmarkers. -
Preload is CJS (
bridge.cjs) because sandboxed Electron preloads cannot be ESM, even though the rest of the app is"type": "module". -
mainin package.json points atout/main/main.js, notindex.js: electron-vite names the bundle after the entry file. - Bot-attributed history in this snapshot is effectively zero; the line is human-scale commits, not a dependency-bot timeline.
Overview
Snapshot and history
How to contribute
Apps
Systems
Features
Primitives
Background and security
Reference