Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
36a0ee0
automations: the design, and the core — schedule, store, presence, clock
ZeroPoint95 Oct 10, 2026
8735af8
automations: the engine side — the automation tool, its card, and the…
ZeroPoint95 Oct 10, 2026
e677025
memory always: the store keeps rules as memories marked always
ZeroPoint95 Oct 10, 2026
615b911
automations: the clock process, window presence, and no timers on the…
ZeroPoint95 Oct 10, 2026
9d8351d
automations: the window side — the card, the run lines, notifications…
ZeroPoint95 Oct 10, 2026
bd57c18
memory always: rules ride every turn and task, /always, the memory pl…
ZeroPoint95 Oct 10, 2026
a2b8a87
automations: delete the v1 resident's scheduler
ZeroPoint95 Oct 10, 2026
59ef8aa
automations: over --host and --at — the far machine's store on the wi…
ZeroPoint95 Oct 10, 2026
bd0f03c
docs: the v1 scheduler is gone
ZeroPoint95 Oct 10, 2026
e466272
automations: the demo home seeds automations, not standing orders
ZeroPoint95 Oct 10, 2026
e80ddad
automations: the place, the typed command and the quit warning; stand…
ZeroPoint95 Oct 10, 2026
1a8f038
Merge branch 'zeropoint95/automations-remote' into zeropoint95/codeaf…
ZeroPoint95 Oct 10, 2026
d00796d
Merge branch 'zeropoint95/automations-demo-home' into zeropoint95/cod…
ZeroPoint95 Oct 10, 2026
34aedda
Merge branch 'zeropoint95/automations-drop-v1-scheduler' into zeropoi…
ZeroPoint95 Oct 10, 2026
c8d4d24
Merge branch 'zeropoint95/automations-memory-always' into zeropoint95…
ZeroPoint95 Oct 10, 2026
193e984
automations: the hints teach automations, and the standing words leav…
ZeroPoint95 Oct 10, 2026
61022e9
automations: the standing engine leaves the session, the doors and th…
ZeroPoint95 Oct 10, 2026
f6b59b2
automations: watch names the idea, and the standing purpose goes
ZeroPoint95 Oct 10, 2026
98cc3e0
automations: the docs say what was built
ZeroPoint95 Oct 10, 2026
9ebe4b3
automations: the kind's answer row is said to be the superset it is
ZeroPoint95 Oct 10, 2026
aa19b52
automations: the reading says why it is handed its palette
ZeroPoint95 Oct 10, 2026
c3dfddd
e2e: automations replace standing orders in the end-to-end suite
ZeroPoint95 Oct 10, 2026
d5a6828
automations: the tui3 and session test builds compile again
ZeroPoint95 Oct 10, 2026
f1f6121
Merge branch 'zeropoint95/automations-e2e' into zeropoint95/codeaf-cr…
ZeroPoint95 Oct 10, 2026
8c4a8a6
automations: the e2e timing notes stop promising a standing pass
ZeroPoint95 Oct 10, 2026
311c889
automations: the chat manual says what replaced standing orders
ZeroPoint95 Oct 10, 2026
b6eb3aa
Merge branch 'zeropoint95/automations-manual' into zeropoint95/codeaf…
ZeroPoint95 Oct 10, 2026
044ef81
automations: internal/standing is deleted
ZeroPoint95 Oct 10, 2026
158f328
automations: home's tip leads with the command
ZeroPoint95 Oct 10, 2026
5b485ae
automations: a collection cannot gain a standing item
ZeroPoint95 Oct 10, 2026
aa1c7e8
automations: a conversation switched to is told what it missed
ZeroPoint95 Oct 10, 2026
9e93a19
automations: the manual says when an errand that went nowhere is cleared
ZeroPoint95 Oct 10, 2026
dea40e8
automations: gofmt
ZeroPoint95 Oct 10, 2026
56a9817
automations: the complexity ratchet holds the automations engine
ZeroPoint95 Oct 10, 2026
1385147
automations: comments stop describing standing orders as live
ZeroPoint95 Oct 10, 2026
1367bd7
Merge the comment sweep into zeropoint95/codeaf-cron-system-7b4f2b
ZeroPoint95 Oct 10, 2026
67a4d69
automations: a run of work stops at the daily spending limit
ZeroPoint95 Oct 10, 2026
ca9edde
automations: the suites pass without standing orders
ZeroPoint95 Oct 10, 2026
4b8f63f
fix: ask an ask-here errand's approvals in its own pane
ZeroPoint95 Oct 13, 2026
d20f8a6
Merge remote-tracking branch 'origin/dev' into zeropoint95/modest-sha…
ZeroPoint95 Oct 13, 2026
809d5f6
Merge remote-tracking branch 'origin/dev' into zeropoint95/codeaf-cro…
ZeroPoint95 Oct 14, 2026
441fa4a
Merge the ask-here approvals fix into zeropoint95/codeaf-cron-system-…
ZeroPoint95 Oct 14, 2026
e0d1528
automations: the word stands on the tab bar, between memory and spend
ZeroPoint95 Oct 14, 2026
194b08a
automations: banners through the terminal, closing pauses, and watche…
ZeroPoint95 Oct 14, 2026
24251fd
automations: the demo's cut-off run is one the person stopped, and th…
ZeroPoint95 Oct 14, 2026
af19a1c
Merge remote-tracking branch 'origin/dev' into zeropoint95/codeaf-cro…
ZeroPoint95 Oct 14, 2026
59bf1ab
automations: the change entry for #1831
ZeroPoint95 Oct 14, 2026
723b98d
automations: a run's whole result is read in its history, and its ban…
ZeroPoint95 Oct 14, 2026
a8a7176
automations: the review's fixes
ZeroPoint95 Oct 14, 2026
afeb075
Merge remote-tracking branch 'origin/dev' into zeropoint95/codeaf-cro…
ZeroPoint95 Oct 14, 2026
a05dde0
docs: the guide's tool table names automation, not the removed stand
ZeroPoint95 Oct 14, 2026
aa30148
Merge remote-tracking branch 'origin/dev' into zeropoint95/codeaf-cro…
ZeroPoint95 Oct 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
16 changes: 10 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ and the rule that changing any cap changes the doc in the same commit — are in
[PERF.md](PERF.md).

`make demo-home` builds a **throwaway home with something on every place** — three
projects, twelve conversations, standing orders, memories, a fourteen-day spending
projects, twelve conversations, automations, memories, a fourteen-day spending
ledger — and opens `bin/codeaf` against it with `HOME` pointed there. Use it when you
want to SEE a page full: on a machine that has just started using codeaf the standing,
want to SEE a page full: on a machine that has just started using codeaf the automations,
memory and spend pages correctly draw nothing, which is indistinguishable from a page
that is broken. It never touches `~/.codeaf`. The seeder is `cmd/codeaf-demo-home` and
`docs/design/home-rethink/HANDOFF.md` says what is in the fixture and how to add to it.
Expand Down Expand Up @@ -356,14 +356,18 @@ terminal against a real model, and it is how a wave verifies that the surface
still behaves:

```sh
make test-e2e-tui # TestTUIE2E alone, ~17m, 40m ceiling
make test-e2e-tui # TestTUIE2E alone, 40m ceiling
make test-e2e # whole tagged package, 120m ceiling
go test -tags e2e -run TestTUIE2E -count=1 -timeout 40m -v ./internal/e2e/
```

It needs a provider key and `tmux`, costs a few cents. `TestTUIE2E` alone is
about **seventeen minutes** (most of it one subtest waiting out a five-minute
standing pass). The whole tagged package does not fit in forty minutes —
It needs a provider key and `tmux`, costs a few cents. `TestTUIE2E` alone was
about **seventeen minutes**, most of it one subtest waiting out a five-minute
standing pass; that subtest went with standing orders on 2026-10-10, and the
suite has not been timed since. Automations have a keyless proof of their own —
`go test -tags e2e -run TestAutomationsE2E -count=1 -v ./internal/e2e/` drives
the real binary against a scripted model endpoint, so it needs only `tmux` and
`bin/codeaf`. The whole tagged package does not fit in forty minutes —
ManualOnTheWire, QuestionsE2E and the roomfeed twins run first and eat the
budget — so `make test-e2e` gives it two hours. It SKIPS
rather than fails with no key, no tmux or no `bin/codeaf`, so run `make build`
Expand Down
16 changes: 9 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -310,28 +310,30 @@ test-packed-manual: embed
test-remote:
go test -tags docker_e2e -count=1 -run TestRemoteTwoMachines -timeout 20m ./internal/e2e/

# THE AMBIENT SURFACE, ALONE. TestTUIE2E fits in about seventeen minutes; the
# full tagged package does not fit in forty (ManualOnTheWire, QuestionsE2E and
# the roomfeed twins run first and eat the budget). This is the door for the
# seventeen-minute ambient proof. Needs OPENROUTER_API_KEY, tmux and bin/codeaf.
# THE CHAT SURFACE, ALONE. TestTUIE2E fits in forty minutes where the full
# tagged package does not (ManualOnTheWire, QuestionsE2E and the roomfeed twins
# run first and eat the budget). It used to take about seventeen, most of them
# one subtest waiting out a standing pass that went with standing orders on
# 2026-10-10. Needs OPENROUTER_API_KEY, tmux and bin/codeaf.
test-e2e-tui: build
go test -tags e2e -count=1 -timeout 40m -v -run '^TestTUIE2E$$' ./internal/e2e/

# THE WHOLE TAGGED PACKAGE. Two hours is the measured fit on Spark once every
# live-model lane is included; prefer test-e2e-tui when only the ambient surface
# live-model lane is included; prefer test-e2e-tui when only the chat surface
# is under change.
test-e2e: build
go test -tags e2e -count=1 -timeout 120m -v ./internal/e2e/

# ── the demo home ───────────────────────────────────────────────────────────
#
# A HOME WITH SOMETHING ON EVERY PLACE, FOR LOOKING AT. On a machine that has
# just started using codeaf the standing store, the memory store and the
# just started using codeaf the automations store, the memory store and the
# spending ledger are empty, and every one of those pages correctly draws
# nothing — which is the emptiness law working and is also indistinguishable
# from a page that is broken. This builds a THROWAWAY home somewhere else and
# opens the real binary against it, so all of it can be seen full without a
# single invented row landing in ~/.codeaf.
# single invented row landing in ~/.codeaf. The window it opens starts no
# automations clock (CODEAF_NO_AUTOMATIONS), so nothing invented ever runs.
#
# It prints the directory it built and the command to open it again, so the same
# home can be returned to:
Expand Down
32 changes: 26 additions & 6 deletions PERF.md
Original file line number Diff line number Diff line change
Expand Up @@ -1516,12 +1516,12 @@ that pays some back lowers it in the same commit. It replaced a `t.Logf`, which
nothing in the Makefile passes `-v` to — the one line saying the prefix was
thousands of bytes over was printed where nobody would ever see it.

The bill is not spread thin: `stand` is **9,607 bytes**, more than a quarter of
the full tool block and nearly twice the next heaviest, and on a
sixteen-thousand-token window it is roughly one token in six of everything that
person has before they have said anything. Trimming it is a change to what the
model is told, so it is owed by whoever owns the standing belt and not by this
gate.
The bill was not spread thin: `stand` was **9,607 bytes**, more than a quarter
of the full tool block and nearly twice the next heaviest, and on a
sixteen-thousand-token window it was roughly one token in six of everything that
person had before they had said anything. Trimming it was a change to what the
model is told, so it was owed by whoever owned the standing belt and not by this
gate — and it was paid when automations replaced it (2026-10-10, below).

**And the prefix is not the same size on every machine, which is why both
figures are the widest machine's.** `grep` says a longer sentence about itself
Expand Down Expand Up @@ -1562,6 +1562,14 @@ both arms, and the caps rise by exactly that over sec's: measured on dev
`baa2d7f0f` with sec (2026-10-07), the full cap is **57,817** bytes and the lean
cap **50,189**, both dated in `prefixWaivers`.

**Automations replace standing orders, and the `stand` bill is paid (2026-10-10).**
`stand` and its **9,607** bytes leave every belt that carried them; `automation`,
a smaller tool for the same sentences, takes its place, and the page's one
sentence about leaving something behind stays the same length. The full prefix
measures **52,713** bytes and the lean **44,935**, and both waivers fall to sit
exactly on the measurement: the full cap is **52,713** (4,713 over its target)
and the lean cap **44,935** (13,435 over).

## Following through on a completion claim

A turn may decline handoff once per request when its own continuation says no
Expand Down Expand Up @@ -2917,6 +2925,18 @@ cost grows with that partition, rather than losing punctuation or older duplicat
behind a retrieval ceiling. The canonical event journal is not periodically pruned;
projection/context work is bounded, while durable history continues to grow.

Rules — memories marked always — ride in message[0] and close every task brief, so
their block is bounded twice: at most **12 rules** (`alwaysBlockMost`) and **2,400
runes** of rule lines (`alwaysBlockRunes`, half the routed block's 4,800), whole rules
only, the newest waiting behind a `…N more` line. The block carries no age and no
clock-derived byte, so it is byte-identical from turn to turn until a rule changes,
which is what keeps the cached prefix warm (`prefixcache_test.go`). The read is one
statement per turn start through the partial index `memories_always_active`, which
holds only active rules, so it is a seek over the rule count; a failed read keeps the
last block rather than re-pricing the prefix to say nothing. Rules are excluded from
the router's shortlist, the binding reads and the memory tidy, so no line is paid for
twice.

## Conversation deletion completion

Permanent deletion joins the task run's completion channel with
Expand Down
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,15 @@ that includes running your own.

[![pool updated](https://img.shields.io/github/last-commit/Agent-Field/CodeAF/model-pool?label=pool%20updated)](https://github.com/Agent-Field/CodeAF/tree/model-pool)

## Standing orders
## Automations

Rules, reminders and watches are one thing, and you set them up by saying them.
"Never commit straight to main here." "Every Monday, draft the weekly update."
"Tell me when CI goes red." A card asks once; `1` and it stands, in this project
or everywhere, on the same daily spend limit as the rest.

<img src="assets/readme/screens/standing.webp" alt="The standing place: orders, reminders and watches for this project and others, when each last woke and what it cost" width="100%">
Reminders, scheduled work and watches are one thing, and you set them up by
saying them. "Remind me at 6 to leave." "Every Monday at 9, draft the weekly
update." "Tell me when CI on main goes red." A card shows exactly what will run,
when, and what one run may spend; `1` saves it. They run while codeaf is open,
anything missed while it was closed runs once when it opens, and `/automations`
shows each one with its history. A rule for all future work — "never commit
straight to main here" — is a memory marked always.

## Headless is the other front door

Expand All @@ -235,7 +236,7 @@ best answer and records the assumption. `exec` runs one worker with no plan;
Most agents on a remote box mean ssh, tmux, and a terminal that lags on every
key. CodeAF splits in two instead. The screen runs on the machine in front of
you. The conversation runs on the machine that owns the work, and `home` shows
that machine: its projects, tasks and standing orders.
that machine: its projects, tasks and automations.

<img src="assets/readme/anywhere.webp" alt="one conversation on devbox; your terminal on the same machine, your laptop over ssh, and your phone from a mobile terminal over ssh all attach to it" width="100%">

Expand Down Expand Up @@ -269,8 +270,8 @@ when the hosted relay does. [How it works](docs/REMOTE.md).
| where you work | one window, one repository | every project on the machine, from one control room |
| what you do | watch it type | describe work, answer what needs you, decide what lands |
| what runs | one model, one thread | six seats chosen per call, and subharnesses built for one job |
| how long it lasts | one session | conversations, tasks and standing orders that outlive the window |
| without you | it stops | headless, standing orders, a phone in your pocket |
| how long it lasts | one session | conversations and tasks that outlive the window, automations on a clock |
| without you | it stops | headless, automations, a phone in your pocket |

## Performance benchmark

Expand Down
Binary file removed assets/readme/screens/standing.webp
Binary file not shown.
47 changes: 32 additions & 15 deletions cmd/codeaf-demo-home/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ package main
// owner opened the standing page, the memory page and the spend page on their
// own machine and saw nothing, because on their machine those stores are new
// and empty — which is the emptiness law working exactly as designed. The
// answer is not to write invented standing orders, invented memories and
// invented spending into ~/.codeaf, which would make a person's own record a
// lie; it is a SECOND home, somewhere else, that the surface can be pointed at.
// answer is not to write invented automations, invented memories and invented
// spending into ~/.codeaf, which would make a person's own record a lie; it is
// a SECOND home, somewhere else, that the surface can be pointed at.
// So this program never touches the real state root: it writes one directory,
// the one it was given, and the launcher hands that directory to the binary as
// HOME.
Expand All @@ -22,8 +22,8 @@ package main
// its own main package and `bin/codeaf` does not change by a byte.
//
// EVERYTHING IS WRITTEN THROUGH THE ENGINE'S OWN WRITERS — session.SaveMeta,
// session.RecordUsage, session.RecordArtifact, standing.Store, store.Store — so
// what the surface reads back is what the product itself produces. The one
// session.RecordUsage, session.RecordArtifact, automation.Store, store.Store —
// so what the surface reads back is what the product itself produces. The one
// exception is stated where it is made ([writeTranscript]).

import (
Expand Down Expand Up @@ -84,8 +84,8 @@ func run(args []string) error {
fmt.Fprintf(os.Stderr, "\ncome back to this one with:\n make demo-home DEMO_HOME=%s KEEP=1\n", dir)

if *launch == "" {
fmt.Fprintf(os.Stderr, "\nor open it by hand with:\n cd %s && HOME=%s %s\n",
filepath.Join(dir, firstProjectName), dir, surfaceBeside())
fmt.Fprintf(os.Stderr, "\nor open it by hand with:\n cd %s && HOME=%s %s=1 %s\n",
filepath.Join(dir, firstProjectName), dir, demoNoClock, surfaceBeside())
return nil
}
return launchAgainst(dir, *launch)
Expand Down Expand Up @@ -114,8 +114,9 @@ const usageText = `codeaf-demo-home — build a home with something on every pla
--into where to build it; a fresh temporary directory when not given
--keep reuse a directory that already holds a demo home rather than refusing
to write over it, so a second launch sees what the first one left
--launch run that binary against the demo home, with HOME pointed at it and a
presence heartbeat running beside it, and return when it exits
--launch run that binary against the demo home, with HOME pointed at it, the
automations clock off and a presence heartbeat running beside it,
and return when it exits

It writes inside --into and nowhere else. The real state root (~/.codeaf) is
never opened.
Expand All @@ -135,8 +136,8 @@ never opened.
// spellings are two PROJECT BUCKETS for one folder — the fixture's conversations
// under `-tmp-…-codeaf` and the window's own under `-private-tmp-…-codeaf` — so
// home drew the demo project twice, and `enter` on a standing order refused
// because the conversation that asked for it was "elsewhere"
// ([app.homeItemEnter]'s bucket guard). Every path this fixture writes is the
// because the conversation that asked for it was "elsewhere" (the bucket guard
// in internal/tui3's homeItemEnter). Every path this fixture writes is the
// resolved one, so the fixture and the binary agree about what the folder is
// called.
func demoDir(into string, reuse bool) (dir string, fresh bool, err error) {
Expand Down Expand Up @@ -213,13 +214,29 @@ func launchAgainst(dir, binary string) error {
}

// demoEnviron is this process's environment with the codeaf pins that would
// point the surface back at the real machine removed. HOME is set by the
// caller; CODEAF_HOME would override it outright, which is the one variable
// that could silently send a demo launch at the owner's own state root.
// point the surface back at the real machine removed, and the automations
// clock switched off. HOME is set by the caller; CODEAF_HOME would override it
// outright, which is the one variable that could silently send a demo launch at
// the owner's own state root.
func demoEnviron() []string {
return env.EnvironWithout("HOME", home.EnvVar)
return append(env.EnvironWithout("HOME", home.EnvVar, demoNoClock), demoNoClock+"=1")
}

// demoNoClock keeps every window opened on the demo home from starting the
// automations clock ([automation.Startable] reads it): the window still reads
// the store, draws the lines and counts itself open, and nothing runs.
//
// THE FIXTURE'S AUTOMATIONS ARE INVENTED AND THE CLOCK WOULD RUN THEM FOR REAL.
// A window starts `codeaf clock` against the home it was opened on, and the
// clock takes every slot that is due — the morning sweep and the dependency
// bump are unattended sessions on the person's own key, and the watch on CI
// runs a command and asks a model every fifteen minutes. So without this the
// first look at the demo would spend real money on invented work, which is the
// rule the task graph already keeps for the same reason (seed_room.go). The
// cost is that an automation made INSIDE the demo is saved and never runs; the
// demo is for looking at, and its history is the thing on show.
const demoNoClock = "CODEAF_NO_AUTOMATIONS"

// resolveDemoDir is the directory with its symlinks followed, and the directory
// itself where they cannot be — a path that does not resolve is not a reason to
// refuse to build a fixture in it.
Expand Down
Loading
Loading