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
2 changes: 1 addition & 1 deletion LOGIC.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The Framework: autonomous AI programming. The user registers repositories as pro
- `packages/agent-driver` — the driver [2] seam: one contract for driving a coding agent as a black box, with the Claude Code, Codex, GitHub Actions and fake implementations; the product adds its own cloud-session implementation behind the same contract. The Framework prompts one turn at a time, lets the coding agent's own loop run to completion, and learns everything from the turn's final message: it never gates on the agent's individual tool calls, holds no model key, and runs on the user's own subscription.
- `packages/agent-data` — a branch of the project's repository used as a file store: the `agent-data` branch [6], checked out under `.branches/`, written through one sync → commit → push cycle that re-applies when a push loses a race. A library, not a skill: read by code, never by an agent. Every skill depends on it; nothing else does.
- `packages/skill-branches`, `packages/skill-tickets`, `packages/skill-queue`, `packages/skill-logs` — the four skills [8]: an agent's own checkout [3] and branch; the tickets with their plans and claims; the agent queue [7]; the record of every run [18]. Tickets, queue, runs and routine locks live on the `agent-data` branch, never on a code branch, so the default branch stays code only. No skill depends on another.
- `packages/routines` — the routines the daemon fires on its own, one skill file each and no code: jobs that compose the four skills [8], starting with the queued work; The Framework depends on it and fires a routine by its slash command.
- `packages/skill-work-queue` — the first command skill: a job for an agent, one skill file and no code, composing the four skills [8] without naming one; the daemon fires it by its slash command, `/work-queue`. One package per command, `@gemstack/skill-<command>`; The Framework depends on it for now.
- `packages/chrome-extension` — the far end of the Claude web bridge [14], a Chrome extension reading claude.ai in a signed-in browser; it talks to the daemon over HTTP only.
- `packages/the-framework.ai` — the marketing site at https://the-framework.ai; it presents the product and shares no code with it.
- `.github/workflows` — every push builds, type-checks and tests the monorepo; the website deploys itself from the default branch; and one workflow is the far end of the `github-actions` driver implementation, running one turn per workflow run.
Expand Down
2 changes: 1 addition & 1 deletion packages/LOGIC.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The deliverables The Framework ships, one directory each. The product is the `fr
- **The `tickets` skill** (`skill-tickets/`) - the `@gemstack/skill-tickets` npm package: the project's tickets with their plans and claims on the `agent-data` branch, the `tickets` command that reads, writes, claims and closes them, and the skill text. Depends on `agent-data`.
- **The `queue` skill** (`skill-queue/`) - the `@gemstack/skill-queue` npm package: the agent queue on the `agent-data` branch, the `queue` command that reads it, adds an entry at a priority and takes one off, and the skill text. Depends on `agent-data`.
- **The `logs` skill** (`skill-logs/`) - the `@gemstack/skill-logs` npm package: the record of every run agents made on a project, on the `agent-data` branch, and the read-only `logs` command; the product writes every run through it. Depends on `agent-data`.
- **The routines** (`routines/`) - the `@gemstack/routines` npm package: the jobs a daemon fires on its own, one skill file each under `skills/<name>/` and no code, each composing the capability skills of a project; the queued work first.
- **The `work-queue` command** (`skill-work-queue/`) - the `@gemstack/skill-work-queue` npm package: a command skill, one `SKILL.md` and no code, the job of working one queued task off the agent queue; it composes the capability skills of a project without naming one. One package per command; the daemon fires it by its slash command.
- **The Claude web bridge's extension** (`chrome-extension/`) - a Chrome extension, not an npm package: the far end of the Claude web bridge [5], reading claude.ai in a signed-in browser. Talks to the product over HTTP only.
- **The website** (`the-framework.ai/`) - the marketing site at https://the-framework.ai. Presents the product; shares no code with it.

Expand Down
2 changes: 1 addition & 1 deletion packages/framework/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"dependencies": {
"@base-ui-components/react": "1.0.0-rc.0",
"@gemstack/agent-data": "workspace:*",
"@gemstack/routines": "workspace:*",
"@gemstack/skill-work-queue": "workspace:*",
"@gemstack/skill-branches": "workspace:*",
"@gemstack/skill-logs": "workspace:*",
"@gemstack/skill-queue": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/framework/prompts/presets/LOGIC.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
The fourteen presets: the canned prompts behind the launcher's buttons and the daemon's rotation routines [2], one markdown file each. Five of them are quality passes over a target the user names; one sweeps the code and queues quality work; four are product management, proposing or picking tickets; four are the routines that keep the tickets and the agent queue [4] fresh. The routine that works the queue is not a preset: it is the skill file `skills/work-queue/SKILL.md` of the `@gemstack/routines` package, which only the daemon fires. The table in `src/preset-catalog.ts` says which button or routine each backs, in which order the launcher shows them, and appends the queue-only rule of `../triage_scope.md` to the two triage presets.
The fourteen presets: the canned prompts behind the launcher's buttons and the daemon's rotation routines [2], one markdown file each. Five of them are quality passes over a target the user names; one sweeps the code and queues quality work; four are product management, proposing or picking tickets; four are the routines that keep the tickets and the agent queue [4] fresh. The routine that works the queue is not a preset: it is the `SKILL.md` of the `@gemstack/skill-work-queue` package, a command skill only a person or the daemon fires. The table in `src/preset-catalog.ts` says which button or routine each backs, in which order the launcher shows them, and appends the queue-only rule of `../triage_scope.md` to the two triage presets.

## Context

Expand Down
10 changes: 5 additions & 5 deletions packages/framework/src/auto-pm.LOGIC.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Decides, once per look [1] and per project, whether the daemon may spend the account's quota [2] on work nobody asked for, and on what. Auto PM [3] either starts an agent [6] on the queued work [4] because the `agent-data` branch [11] moved, or, once a run found nothing queued, refills the agent queue [5] by firing the next routine [7] of a fixed rotation. The daemon reads no queue and names no skill: it reads the head of the branch, and it starts the queued work with one slash command, `/work-queue`, the routine skill [22] shipped with The Framework. Every reason not to start is a sentence the daemon logs and the dashboard shows.
Decides, once per look [1] and per project, whether the daemon may spend the account's quota [2] on work nobody asked for, and on what. Auto PM [3] either starts an agent [6] on the queued work [4] because the `agent-data` branch [11] moved, or, once a run found nothing queued, refills the agent queue [5] by firing the next routine [7] of a fixed rotation. The daemon reads no queue and names no skill: it reads the head of the branch, and it starts the queued work with one slash command, `/work-queue`, the command skill [22] shipped with The Framework. Every reason not to start is a sentence the daemon logs and the dashboard shows.

## Context

Expand Down Expand Up @@ -29,7 +29,7 @@ Decides, once per look [1] and per project, whether the daemon may spend the acc
[19] checkout: an agent's own working copy of the project: a git worktree under the project's `.branches/` directory, named as its branch.
[20] agent id: an agent's stable id, derived from the moment it started; it names the agent's checkout directory, its branch until the agent names it, and its run.
[21] holder: who a claim names: the agent's id when the daemon started the agent, else the branch the `tickets` command ran on.
[22] routine skill: a skill file (`SKILL.md`) marked so that only a person or the daemon invokes it, whose body is the job's prompt; the daemon starts the agent with the skill's slash command and the coding agent's harness expands it.
[22] command skill: a skill file (`SKILL.md`) marked so that only a person or the daemon invokes it, whose body is the job's prompt, shipped as its own package; the daemon starts the agent with the skill's slash command and the coding agent's harness expands it.
[23] the heartbeat: one run on the queued work a day when nothing moved, the belt for a move the daemon missed.
[24] the chain: the queued work firing again as its run ends, because the run's own commits moved the branch; it ends with a run that moves nothing.

Expand All @@ -53,7 +53,7 @@ Decides, once per look [1] and per project, whether the daemon may spend the acc
- **Starting, and stopping** - the first refused start ends the batch, claims of agents that never started are released, and a stopped daemon spawns nothing more.
- **"Run now": a look a person asked for** - runs with the preference off and without the cooldown, scoped to one project or one routine; the queued work's row starts an agent on the queue whether or not the branch moved.
- **What the last look reports** - the dashboard shows whether the preference was on, when the look ran, when the next is due, and one sentence per project; the log gets a stand-down only when it is news.
- **The routines** - the queued work is the routine skill `work-queue`; the rest are built from the presets: name, prompt, label and tooltip come off the preset; what a routine does (works the queue, fans out, takes a lock, auto-merges) is declared on the routine, never matched by name.
- **The routines** - the queued work is the command skill `work-queue`; the rest are built from the presets: name, prompt, label and tooltip come off the preset; what a routine does (works the queue, fans out, takes a lock, auto-merges) is declared on the routine, never matched by name.

## Business logic

Expand All @@ -75,7 +75,7 @@ See `## Context`.

#### Business logic

A project whose branch moved [15] starts one agent [6] told `/work-queue`, the routine skill [22] shipped in the `@gemstack/routines` package and linked into every checkout the daemon makes (`daemon-runtime.ts`), unattended [16], with its handoff [18] at `merge`, since what it implements has already been triaged onto the queue where a human could have vetoed it. One agent per move, however high the concurrency cap: the next start needs the branch to move again, which the agent's own commits do. The start spends the move and the rotation's turn alike: whether the queue wants refilling is for this run to find out. A commit the daemon wrote itself is not a move: the run's record the daemon writes at teardown, a routine lock [10] it takes or drops, a claim [9] it mints for a plan agent all carry the trailer, on this machine and on every other machine running the daemon, so a record never starts the next run and two daemons on one branch never fire empty runs at each other's records. A person's writes from the dashboard — queue an entry, release a claim — carry no trailer and are moves: a person asking for work is exactly what should start a run.
A project whose branch moved [15] starts one agent [6] told `/work-queue`, the command skill [22] shipped as the `@gemstack/skill-work-queue` package and linked into every checkout the daemon makes (`daemon-runtime.ts`), unattended [16], with its handoff [18] at `merge`, since what it implements has already been triaged onto the queue where a human could have vetoed it. One agent per move, however high the concurrency cap: the next start needs the branch to move again, which the agent's own commits do. The start spends the move and the rotation's turn alike: whether the queue wants refilling is for this run to find out. A commit the daemon wrote itself is not a move: the run's record the daemon writes at teardown, a routine lock [10] it takes or drops, a claim [9] it mints for a plan agent all carry the trailer, on this machine and on every other machine running the daemon, so a record never starts the next run and two daemons on one branch never fire empty runs at each other's records. A person's writes from the dashboard — queue an entry, release a claim — carry no trailer and are moves: a person asking for work is exactly what should start a run.

### The chain, and after an empty run the rotation

Expand Down Expand Up @@ -280,7 +280,7 @@ Before deciding, every agent this loop started on the project and has not yet be

#### Business logic

- The queued work [4] is the routine skill [22] `work-queue`: its name is the skill's, its prompt is the slash command `/work-queue`, its label "Work the queue" and its tooltip "Work one queued task off the agent queue, unattended." are written here, and it is declared as working the queue and as auto-merging its pull request. The skill file itself is `skills/work-queue/SKILL.md` in the `@gemstack/routines` package, which The Framework depends on.
- The queued work [4] is the command skill [22] `work-queue`: its name is the skill's, its prompt is the slash command `/work-queue`, its label "Work the queue" and its tooltip "Work one queued task off the agent queue, unattended." are written here, and it is declared as working the queue and as auto-merging its pull request. The skill file itself is the `SKILL.md` of the `@gemstack/skill-work-queue` package, which The Framework depends on.
- Each preset-backed routine carries the preset's stable name, which is what the rotation's position and the switched-off list key on; the prompt rendered from the preset; and the preset's label and one-line tooltip, read off the preset so a relabeled preset relabels its routine and the sentence the launcher shows for a preset and the sentence the routines list shows for its routine are the same sentence.
- Only the maintenance routine carries a separate description line, "sweeping the codebase for maintenance work", because "Maintenance" names its preset rather than the work; the other routines' labels read as what they do, so their rows stay one line and their log lines say the label itself.
- The planning routine is declared as fanning out [14]; the triage routines each declare their routine lock [10].
Expand Down
8 changes: 4 additions & 4 deletions packages/framework/src/auto-pm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,13 +544,13 @@ test('a stand-down is logged when it is news, not once a minute (#1774)', async
assert.equal(loop.report().outcomes[0]?.message, 'there is no job to run')
})

test('AUTO_PM_WORK_JOB fires the routine skill by its slash command, and lands its own PRs (#1216/#1774)', () => {
test('AUTO_PM_WORK_JOB fires the command skill by its slash command, and lands its own PRs (#1216/#1774)', () => {
// The prompt is the skill's name as a slash command; the agent's harness expands it. The skill
// file ships in the routines package, and only a person or the daemon may invoke it.
// file ships as its own package, and only a person or the daemon may invoke it.
assert.equal(AUTO_PM_WORK_JOB.prompt, `/${WORK_QUEUE_SKILL_NAME}`)
assert.equal(AUTO_PM_WORK_JOB.works, true)
const routines = dirname(createRequire(import.meta.url).resolve('@gemstack/routines/package.json'))
const skill = readFileSync(join(routines, 'skills', WORK_QUEUE_SKILL_NAME, 'SKILL.md'), 'utf8')
const pkg = dirname(createRequire(import.meta.url).resolve('@gemstack/skill-work-queue/package.json'))
const skill = readFileSync(join(pkg, 'SKILL.md'), 'utf8')
assert.match(skill, new RegExp(`^---\\nname: ${WORK_QUEUE_SKILL_NAME}\\n`))
assert.match(skill, /\ndisable-model-invocation: true\n/)
// What the agent is told: one task, commit but do not push, committed counts as published,
Expand Down
8 changes: 4 additions & 4 deletions packages/framework/src/auto-pm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,10 @@ export const AUTO_PM_JOBS: readonly AutoPmJob[] = [
]

/**
* The routine skill the daemon fires on the queued work (#1774): `skills/work-queue/SKILL.md` in
* the `@gemstack/routines` package, linked into every checkout the daemon makes, marked so that
* only a person or the daemon invokes it. Its prompt is the slash command; the agent's harness
* expands it.
* The command skill the daemon fires on the queued work (#1774): the `SKILL.md` of the
* `@gemstack/skill-work-queue` package, linked into every checkout the daemon makes, marked so
* that only a person or the daemon invokes it. Its prompt is the slash command; the agent's
* harness expands it.
*/
export const WORK_QUEUE_SKILL_NAME = 'work-queue'

Expand Down
Loading
Loading