Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions packages/the-framework/SPEC.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ One agent's action bar: what the agent is on the left — its branch, state, and
## Flows

- Everything the user can do to the agent collapses into one overflow menu; only the end-of-work hand-off's next step (push / open PR) stays out as a visible button, since it is the one thing that moves the work forward.
- The agent's state (exactly one of stopped, ready for merge, failed, building, finished) reads beside the branch facts instead of spending a banner row on one word.
- The agent's state (exactly one of stopped, ready for merge, failed, building, publishing, finished) reads beside the branch facts instead of spending a banner row on one word.
- The user sees one bar whether the agent is live or finished, and always one row: the label gives up width before the controls ever wrap.

## Before modifying/creating SPEC.md files
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
The two Discord setup dialogs — the bot and notifications — that explain the integration, take its credential, and toggle the matching preference, so Discord is set up inside the product instead of by editing the daemon's environment and restarting it.
The Discord notifications setup dialog: it explains the integration, takes the webhook credential, and toggles the matching preference, so Discord is set up inside the product instead of by editing the daemon's environment and restarting it.

## Flows

- A credential is write-only: it goes to the daemon and never comes back, so a stored one reads "saved" with Replace and Remove instead of a field holding a secret.
- A credential set in the daemon's environment wins over a stored one, so that case is reported as set-by-environment and not editable here, rather than offering an edit the daemon would ignore. A host that stores no credentials says so instead of offering a field.
- Obviously-wrong input is refused before it is sent, and anything typed is wiped when the dialog closes so no secret lingers in a field.
- The enable toggle is independent of the credential: it can be turned on first and starts working once the credential is set.
- Each dialog's one-line description is shared with the onboarding checklist row that opens it, so the two never tell different stories.
- The dialog's one-line description is shared with the onboarding checklist row that opens it, so the two never tell different stories.

## Before modifying/creating SPEC.md files

Expand Down
12 changes: 6 additions & 6 deletions packages/the-framework/dashboard/components/DiscordDialogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Dialog } from './ui/dialog.js'
import { Button } from './ui/button.js'
import { usePreferences, updatePreferences, discordEnabled } from '../lib/preferences.js'

// The two Discord setup dialogs (#958, credentials in #1095).
// The Discord setup dialog (#958, credentials in #1095).
//
// #958 shipped these as explainers: they described what to set and told you to edit the daemon's
// environment and restart it, which is what made Discord the one onboarding step you could not
Expand All @@ -23,7 +23,7 @@ import { usePreferences, updatePreferences, discordEnabled } from '../lib/prefer
export const DISCORD_WEBHOOK_DESCRIPTION =
'Delivers notifications to Discord, so an agent waiting on you reaches you with no dashboard open.'

/** What both dialogs take from their host: what the daemon holds, and a reload for after a save. */
/** What the dialog takes from its host: what the daemon holds, and a reload for after a save. */
interface DialogProps {
open: boolean
onOpenChange: (open: boolean) => void
Expand Down Expand Up @@ -70,10 +70,10 @@ interface ToggleSpec {
}

/**
* The shell both dialogs are: explain, take the credential, toggle the preference. One component
* rather than two near-copies, because what differs between them is a credential name and its
* words — while everything that could drift (what "configured" means, what an env-set credential
* does to the form, how a save is reported) is behaviour they have to share.
* The dialog's shell: explain, take the credential, toggle the preference. Kept apart from the
* wiring above so the behaviour that must not drift (what "configured" means, what an env-set
* credential does to the form, how a save is reported) lives in one place, whatever credential
* a dialog is for.
*/
function CredentialDialog({
open,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
The shell header's single notifications bell, making the model legible: where notifications are delivered, and which categories trigger them.
The single notifications bell in the sidebar's utility footer, making the model legible: where notifications are delivered, and which categories trigger them.

## Flows

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import {
DropdownMenuSeparator,
} from './ui/dropdown-menu.js'

// One "Notifications" bell in the shell header (#676), replacing the three loose icons (bell /
// Discord / activity). It makes the model legible: the bell and Discord are *delivery methods*
// (where a notification goes), "New activity" is a *category* on top of the always-on "needs you"
// pings. The trigger shows an active state + dot when a method is effectively on; the popover
// groups and labels every toggle. The underlying prefs and hooks are unchanged — this is purely
// the header control that writes them. The Discord *bot* (#680) sits in its own "Chat" group
// One "Notifications" bell in the sidebar's utility footer (#676), replacing the three loose
// icons (bell / Discord / activity). It makes the model legible: the bell and Discord are
// *delivery methods* (where a notification goes), "New activity" is a *category* on top of the
// always-on "needs you" pings. The trigger shows an active state + dot when a method is
// effectively on; the popover groups and labels every toggle. The underlying prefs and hooks are
// unchanged — this is purely the control that writes them. The Discord *bot* (#680) sits in its own "Chat" group
// rather than under a delivery method: it is the one control here that takes messages in.

export function NotificationsMenu() {
Expand Down
2 changes: 1 addition & 1 deletion packages/the-framework/dashboard/components/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The dashboard's React component catalog: every page, panel and control the brows

## Flows

- One shared shell frames every route: the left sidebar (brand, New launcher, Overview / Tickets / Projects navigation, recent agents, utility footer) and a right rail of agent-pushed views, surfaced docs and project history. Its pages are the Overview board, the project home/launcher, one agent's view, the cross-project tickets pages (list, per-ticket detail, per-ticket plan), Settings, and not-found.
- One shared shell frames every route: the left sidebar (brand, New launcher, Overview / Tickets / Projects navigation, recent agents, utility footer) and a right rail of the agent's files, agent-pushed views, its browser, and surfaced docs. Its pages are the Overview board, the project home/launcher, one agent's view, the cross-project tickets pages (list, per-ticket detail, per-ticket plan), Settings, and not-found.
- The agent surface is a transcript with its controls inline: an action bar carrying the branch / PR / handoff and the one menu of agent actions, the event feed rendering its questions as answerable cards and its browser screencast in place, the changes and handoff panels, and one composer that starts, steers, stops and resumes — in a stable frame, so an ending never blanks what you are reading.
- The Overview's widgets each show one slice of what the daemon knows: quota pace, agents working now, the Human Queue (what currently waits on a person — an agent's question, a PR to review), the AI queue (every project's open `TODO_AGENTS.md` items), routine work, hot tickets, activity and outcomes, and an onboarding checklist whose steps tick off real facts rather than clicks.
- The launcher's controls — presets, driver/model and option menus, the Context selector, the system-prompt preview — read and write the same preferences and mappings the agent itself uses, so no surface can disagree with the agent it configures.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The launcher form that starts an agent in the selected project: the shared compo

- A typed prompt starts an attended conversation. A preset starts unattended routine work: it ends on its own once the agent's work settles, firing the hand-off it was armed with — how far the work publishes, up to push, PR, or merge.
- The options sent and the prompt previewed come from the same mapping the agent uses, so the form cannot disagree with the agent it starts; a picked device relays the start to that machine, the device's secret token riding in memory only — never persisted.
- Preflight warnings spend words before the agent is spent, and never block. They cover: a driver CLI that cannot start — the GitHub CLI checked only when a PR or merge is armed, and nothing probed for Actions or device targets; a repo whose disabled auto-merge makes an armed merge land immediately; and Haiku's known skipping of the finish step, which leaves a publishing run an unmerged draft PR.
- Preflight warnings spend words before the agent is spent, and never block. They cover: a driver CLI that cannot start — the GitHub CLI checked only when a PR or merge is armed, and nothing probed for Actions or device targets; a repo whose disabled GitHub auto-merge means an armed merge is handled by the daemon's own merge-on-green, which works only while the daemon runs; and Haiku's known skipping of the finish step, which leaves a publishing run an unmerged draft PR.
- A start answers immediately: an optimistic row for the run appears in the sidebar and the view jumps to the agent before its record exists.

## Before modifying/creating SPEC.md files
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ An agent's options as one table with every rule between them already applied, so
## Flows

- A box shows the option's effective value, not the stored one: an option overridden by another reads as off, because off is what the agent will do.
- Transparent turns the whole framework off, so it disables every option below it.
- Transparent turns the framework's own wrapping off, so it disables the options that ride on it — the system-prompt switch, post-merge cleanup, and the browser — while the publish ladder stays the user's to set.
- Publishing is a strict ladder — push branch, open PR, auto-merge — each rung alive only while the one below is on, which makes "publish nothing" expressible and the contradictory PR-without-push state unreachable. Auto-merge is the one rung off by default: publishing a branch is reversible, landing it is not.
- The three publishing boxes store one rung between them: each box writes the rung it means, so unticking one lowers the whole ladder instead of leaving a merge armed over a pull request nobody asked for.
- The browser option is offered only under Claude Code, the one agent it is wired to; every disabled row says why.
Expand Down
3 changes: 2 additions & 1 deletion packages/the-framework/prompts/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ Every word the framework says to a coding agent, authored as markdown: the built

- The system prompt wraps the user's prompt in a working discipline: analyze it and gate on ambiguity or large scope, keep every read and write under the working directory, name the session and do all work on a branch of that name, offer alternatives wherever the best solution is unclear, and signal ready-for-merge only when nothing is left. Without that signal the work is never merged.
- The protocols define the agent's side of the conversation. One teaches how to park on a gate — a question that blocks the agent until the user answers: a choice, a multi-select, a document approval, handing the browser to a human at a login wall — and how to mark the answers that end the agent rather than resume it, so a rejection is not something it is asked to build on. Another teaches the non-blocking signals: show a document, name the session, ready-for-merge, and describe the pull request the framework will open. Per-capability protocols adapt the rest: an agent with a real browser is told when to use it, and a hands-off agent is told gates can never be answered, so it assumes the recommended option and carries on.
- The presets are the one-click task prompts behind the dashboard's buttons: research, the quality reviews (readability, maintainability, security, UX), ticket triage and planning, and draining the queue.
- The presets are the one-click task prompts behind the dashboard's buttons: research, market research, the quality reviews (readability, maintainability, security, UX), ticket triage and planning, updating tickets from GitHub, the three suggestion passes (new features, new tickets, which tickets to work on), the maintenance sweep, and draining the queue.
- One convention teaches how the framework's own records are read and written — the data branch (`tf-data`) — so an agent's bookkeeping never lands on a code branch.
- The format docs teach the repo conventions: tickets as dated proposal files with plan and claim siblings (`.plan.md`, `.lock.md`), and the priority-ordered queue file (`TODO_AGENTS.md`) of confirmed work.
- The before-mergeable prompt is the final quality turn: queue follow-up refactor and security passes when the changes warrant them, and fold what the agent learned into the project's knowledge base (`knowledge-base/*.md`).

Expand Down
4 changes: 2 additions & 2 deletions packages/the-framework/src/SPEC.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
The engine of The Framework: everything that turns an idea, a ticket, or a queue entry into a reviewed pull request — the CLI, the per-machine daemon, the agent runtime that drives the wrapped coding-agent CLI, and the surfaces that watch and steer it.
The engine of The Framework: everything that turns an idea, a ticket, or a queue entry into a pull request for human review — the CLI, the per-machine daemon, the agent runtime that drives the wrapped coding-agent CLI, and the surfaces that watch and steer it.

## User Stories

Expand Down Expand Up @@ -27,7 +27,7 @@ flowchart LR
- The pull request the user gets back is the agent publishing itself: an agent that ends with real work commits, pushes, and opens a PR; an empty one publishes nothing. Merging is authorized by the agent's own ready signal plus an empty backlog of its own, never by configuration alone. How far an agent publishes is one ordinal — each rung including the ones below it — not a set of switches, so an impossible combination cannot be represented.
- When nobody is around, the daemon plays product manager bounded by the account's own quota week: drain the confirmed queue, refill it by triaging and planning tickets (claims committed as lock files beside the tickets, so other machines and cloud agents see them), keep CI green on the PRs it opened, and merge on green.
- Unattended spending stands down past the pro-rated share of the account's week that has elapsed; work the user asked for carries on. The gate is on starting and only on starting — an agent already going is never interrupted to economise.
- What must outlive a process lands in git, not memory: each agent's own event log, archived per user so a repo clean cannot erase it and teammates never conflict, plus tickets and their claims, the queue, and the project log.
- What must outlive a process lands in git, not memory: each agent's own event log, archived per user so a repo clean cannot erase it and teammates never conflict, plus tickets and their claims and the queue — all on the framework's own data branch.
- The subdirectories hold the seams: the CLI adapters (driver), the on-disk agent state (store), the dashboard and its RPC contract, and the end-to-end proofs.

## Rationales
Expand Down
3 changes: 1 addition & 2 deletions packages/the-framework/src/agent-telemetry.SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ The accounting every agent shares, whatever kind it is: naming the session, foll
- The handle for resuming the conversation survives a stop or crash mid-turn: the agent's real session id is surfaced the moment a turn starts, not only when it ends.
- Each turn's spend is folded into a running total as the turn reports, so the dashboard's per-agent spend readout is live rather than final.
- One self-stop exists: an answer that says to stop. It is composed with the stop signal from outside (the Stop button, Ctrl+C), so everything downstream ends the same way whichever fired.
- An unreadable quota never stops the work: a failing quota check means carry on.
- One shared classification of how an agent ended — a user stop, a quota pause (which leaves a note to resume from), or a real failure — so every surface agrees on what "stopped" means.
- One shared classification of how an agent ended — a user stop or a real failure — so every surface agrees on what "stopped" means.

## Rationales

Expand Down
1 change: 0 additions & 1 deletion packages/the-framework/src/agent.SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ One agent: frame it, send it one prompt, honor the gates it answers with, work t
- When a turn stops to ask, the user sees a live question, and the answer continues the same conversation — bounded, so an agent that keeps asking cannot loop forever. With nobody to ask, the recommended option is taken and the agent carries on, which is what an unattended one is for.
- An answer the agent marked as ending it does exactly that, and cleanly: a declined plan reads as a stop rather than a failure, and the agent is never resumed with it. It stops through the same signal a Stop does, so a decline cannot read as a finished agent on one path and a stop on another.
- Once the opening exchange settles, the user's own chat messages each continue the same conversation. An agent whose chat queue goes idle ends itself — unless its own surface is the only one there is, with no dashboard to resume through, in which case it stays parked for the next message.
- The budget and quota stops hold even when nothing runs after the opening turn.
- A build whose opening turn leaves the workspace empty means the agent stalled, so it is re-prompted once with a hard "create it from scratch" directive.
- An agent whose *location* is a cloud session ends at the hand-off, because every later phase would misread the hand-off note as the agent's own reply. Where an agent runs is its own axis, separate from which coding-agent CLI drives it.
- When the user resumes a stopped agent, the message is sent verbatim into the same conversation — the old transcript already carries the framing — while the surrounding flow still runs.
Expand Down
2 changes: 1 addition & 1 deletion packages/the-framework/src/agent.test.SPEC.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Tests the whole agent flow offline: the agent's question gates — one pick, several at once, and plan approval, which is that same gate with two options — the auto-accept fallback when nobody is there to ask, an answer the agent marked as ending it doing exactly that while the same label unmarked stays an ordinary answer, budget and quota stops with resume notes, session links and usage totals, the backlog and chat phases, greenfield versus existing-codebase framing and the once-only scaffold retry, a prompt agent running its text unframed and working no backlog, hand-off agents ending at the hand-off, and resuming a stopped agent verbatim.
Tests the whole agent flow offline: the agent's question gates — one pick, several at once, and plan approval, which is that same gate with two options — the auto-accept fallback when nobody is there to ask, an answer the agent marked as ending it doing exactly that while the same label unmarked stays an ordinary answer, session links and usage totals, the backlog and chat phases, greenfield versus existing-codebase framing and the once-only scaffold retry, a prompt agent running its text unframed and working no backlog, hand-off agents ending at the hand-off, and resuming a stopped agent verbatim.

## Before modifying/creating SPEC.md files

Expand Down
Loading
Loading