Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
774edc5
docs(benchmarks): fix measure-cli script path
hy3560 Sep 25, 2026
32b367f
docs(changelog): record measure-cli path correction
hy3560 Sep 25, 2026
a2babe2
fix(tui3): bind Home task target before clearing its draft
santoshkumarradha Sep 27, 2026
3cbffa9
docs: record Home task target binding correction
santoshkumarradha Sep 27, 2026
f6cf48e
fix(standing): project scoping path normalization, live rail allowanc…
agentfield-bot Sep 27, 2026
8e039e7
fix(standing): resolve budget quotes in engine and honor normalized e…
santoshkumarradha Sep 27, 2026
d5d5303
docs: align change entry filename with pull request number
santoshkumarradha Sep 27, 2026
c2a895d
test(standing): verify live daily rail through launch seam
santoshkumarradha Sep 27, 2026
2bbbffb
fix(standing): preserve approved one-time action in execution handoff
santoshkumarradha Sep 27, 2026
cd39216
fix(tui): share approval receipt with home answers
santoshkumarradha Sep 27, 2026
486db72
docs: record one-time standing approval correction
santoshkumarradha Sep 27, 2026
ffda337
docs(changes): add unreleased changelog entry for issue #1550
agentfield-bot Sep 27, 2026
ea405f2
docs(changes): fix changelog entry format and PR number for #1560 (#1…
agentfield-bot Sep 27, 2026
7a509c7
task: branch commit guard
agentfield-bot Sep 27, 2026
c188310
test(session): add regression tests for standing execution branch iso…
agentfield-bot Sep 27, 2026
576dc9a
Merge reviewed PR #1498 into Santosh/dev2
santoshkumarradha Sep 27, 2026
b04a448
fix(standing): make worktree isolation explicit and preserve unfinish…
santoshkumarradha Sep 27, 2026
7a47b84
fix(standing): keep isolation schema within prompt budget
santoshkumarradha Sep 27, 2026
182bd31
fix(standing): keep isolated work out of ordinary once turns
santoshkumarradha Sep 27, 2026
f32e5c1
fix: record isolated standing copies before worker startup
santoshkumarradha Sep 27, 2026
9aaec29
headless: a blank brief is refused before any work starts
santoshkumarradha Sep 27, 2026
125a204
docs: describe blank brief rejection at the terminal boundary
santoshkumarradha Sep 27, 2026
2cc54aa
docs: use supported surfaces for blank brief entry
santoshkumarradha Sep 27, 2026
b487519
Merge current dev into Santosh/dev2
santoshkumarradha Sep 27, 2026
0b011a5
test(session): join closed program run before fixture cleanup
santoshkumarradha Sep 27, 2026
824821f
test(session): await run completion after its store closes
santoshkumarradha Sep 27, 2026
acb513c
fix(standing): preserve shared timer ownership during implicit setup
santoshkumarradha Sep 27, 2026
c3b23ba
docs: record shared timer ownership correction
santoshkumarradha Sep 27, 2026
c28d4ca
fix(standing): explain unavailable background checks in approval receipt
santoshkumarradha Sep 27, 2026
5ecadc3
Merge reviewed PR #1629 into Santosh/dev2
santoshkumarradha Sep 27, 2026
90f8047
Revert "Merge reviewed PR #1498 into Santosh/dev2"
santoshkumarradha Sep 27, 2026
cb023e2
tui3: a Traffic row shows how long ago, and a press opens that message.
agentfield-bot Sep 25, 2026
3e8dac1
changes: note for #1500
agentfield-bot Sep 25, 2026
c63e395
session: a reminder's clock is joined with a middle dot.
agentfield-bot Sep 25, 2026
7b1de8d
tui3: a Traffic row stays a compact age past a month.
agentfield-bot Sep 25, 2026
cf869f0
changes: note for #1503
agentfield-bot Sep 25, 2026
c4aeecd
test: close the host fixture engine before its profile is removed
santoshkumarradha Sep 27, 2026
efed928
Reveal collapsed work when jumping to a Traffic message
santoshkumarradha Sep 27, 2026
abb990b
Cover Traffic age boundaries and absent timestamps
santoshkumarradha Sep 27, 2026
dda25cd
test(session): join closed program run before fixture cleanup
santoshkumarradha Sep 27, 2026
6aa384a
test(session): await run completion after its store closes
santoshkumarradha Sep 27, 2026
9c0ea16
test(session): join exited program before removing fixture
santoshkumarradha Sep 27, 2026
568bd0e
test(session): observe readings in the handover fixture
santoshkumarradha Sep 27, 2026
658603d
test(session): hold the decision turn until resolution
santoshkumarradha Sep 27, 2026
23d0175
Merge reviewed engine workflow fixes into Santosh/dev2
santoshkumarradha Sep 27, 2026
46d07bd
docs: describe consolidated workflow fixes for PR 1632
santoshkumarradha Sep 27, 2026
7d35c3d
Merge reviewed traffic navigation and reminder presentation fixes
santoshkumarradha Sep 27, 2026
635723f
docs: include reviewed traffic changes in aggregate change entry
santoshkumarradha Sep 27, 2026
671c611
fix: recover and cancel tasks with durable admission state
santoshkumarradha Sep 27, 2026
c73ed6f
docs: identify focused task recovery PR 1619
santoshkumarradha Sep 27, 2026
86fcb7c
test: reproduce missing reply after persistent engine restart
santoshkumarradha Sep 28, 2026
a73ed55
fix: scope reply streams to persistent engine instances
santoshkumarradha Sep 28, 2026
e206760
fix: retain accepted crew policy across task recovery
santoshkumarradha Sep 28, 2026
8341d17
Merge reviewed held task and connection recovery fixes
santoshkumarradha Sep 28, 2026
7297cfb
test: preserve machine isolation while setting run-engine models
santoshkumarradha Sep 28, 2026
93e31a8
test(session): retain narrow worker until its observer captures it
santoshkumarradha Sep 28, 2026
a940db8
test(session): retain wide control worker until observed
santoshkumarradha Sep 28, 2026
b233224
docs: record combined task and connection recovery fixes
santoshkumarradha Sep 28, 2026
4adc864
Merge current dev into Santosh/dev2 preserving task recovery and spen…
santoshkumarradha Sep 28, 2026
52d3bb9
refactor: separate crew restoration and seat retry responsibilities
santoshkumarradha Sep 28, 2026
2a71162
test: join the cancelled recovery driver before fixture cleanup
santoshkumarradha Sep 28, 2026
4517a34
fix: initialize the shared spending day before restoring crew costs
santoshkumarradha Sep 28, 2026
9a2c7cd
fix: snapshot refreshed shared-day spending and expire saved floors
santoshkumarradha Sep 28, 2026
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
10 changes: 10 additions & 0 deletions cmd/codeaf/brief_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,13 @@ func TestABriefMayArriveOnStandardInput(t *testing.T) {
t.Fatalf("brief = %q, want the piped text", text)
}
}

func TestReadTextRejectsAnAllBlankArgumentList(t *testing.T) {
want := noGoalGiven("do").Error()
for _, args := range [][]string{{""}, {" "}, {"", "\t"}} {
text, err := readText("do", args)
if text != "" || err == nil || err.Error() != want {
t.Errorf("readText(%q) = %q, %v; want noGoalGiven", args, text, err)
}
}
}
2 changes: 2 additions & 0 deletions cmd/codeaf/chatv3_host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ func TestTheEngineDoorKeepsTheAmbientSideOnOverAConnection(t *testing.T) {
t.Setenv("CODEAF_HOME", filepath.Join(home, "state"))
t.Setenv("OPENROUTER_API_KEY", "test-key")
t.Chdir(home)
// Close the engine owner, including catalog and pool writers, before this home is removed.
freshEngineProcess(t)

engine, err := bootEngine(remote.Hello{Version: remote.Version}, "", "")
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/codeaf/chatv3_standing.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func v3Standing(profileDir string) *session.Standing {
// The person's own daily budget is what the card quotes beside the
// per-run cap. A profile that cannot be read quotes nothing rather than
// a figure nobody set, which is the emptiness law applied to money.
DailyRailUSD: v3StandingDailyRail(profileDir),
DailyRail: func() float64 { return v3StandingDailyRail(profileDir) },
}
}

Expand Down
15 changes: 12 additions & 3 deletions cmd/codeaf/chatv3_standing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ func TestStandingLivesUnderTheStateRoot(t *testing.T) {
func TestStandingSeamOpensTheStoreAtThatPath(t *testing.T) {
root := filepath.Join(t.TempDir(), "state")
t.Setenv("CODEAF_HOME", root)
seam := v3Standing(t.TempDir())
profile := t.TempDir()
seam := v3Standing(profile)
if seam == nil || seam.Store == nil {
t.Fatal("the door built no standing seam")
}
Expand All @@ -41,8 +42,16 @@ func TestStandingSeamOpensTheStoreAtThatPath(t *testing.T) {
}
// The daily rail is the person's own daily budget row and never a second
// number invented for this.
if seam.DailyRailUSD != v3StandingDailyRail(t.TempDir()) {
t.Fatalf("the seam quotes %v as the daily rail", seam.DailyRailUSD)
if seam.DailyRail == nil {
t.Fatal("the seam must read the current daily rail")
}
for _, budget := range []string{"5", "7"} {
if err := os.WriteFile(filepath.Join(profile, "config.json"), []byte(`{"daily_budget_usd":`+budget+`}`), 0600); err != nil {
t.Fatal(err)
}
if got, want := seam.DailyRail(), v3StandingDailyRail(profile); got != want || got == 0 {
t.Fatalf("daily rail = %v, want %v", got, want)
}
}
}

Expand Down
36 changes: 33 additions & 3 deletions cmd/codeaf/do_engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ func TestDoOnTheRunEngineSeatsEveryLaunchOnTheDoorsModels(t *testing.T) {
if err := os.MkdirAll(profileDir, 0o700); err != nil {
t.Fatal(err)
}
beltModelPins(t, profileDir, map[string]string{
beltProfileModels(t, profileDir, map[string]string{
config.KeyTierWorkerModel: "vendor/profile-worker",
config.KeyTierMastermindModel: "vendor/profile-thinking",
})
Expand Down Expand Up @@ -679,7 +679,7 @@ func TestDoOnTheRunEngineSeatsACheckOnTheCheckModel(t *testing.T) {
if err := os.MkdirAll(profileDir, 0o700); err != nil {
t.Fatal(err)
}
beltModelPins(t, profileDir, map[string]string{
beltProfileModels(t, profileDir, map[string]string{
config.KeyTierLowModel: "vendor/profile-small",
config.KeyTierWorkerModel: "vendor/profile-worker",
config.KeyTierHighModel: "vendor/profile-careful",
Expand Down Expand Up @@ -772,7 +772,7 @@ func TestDoOnTheRunEngineSeatsAnUnpinnedCheckOnTheCrewsChecker(t *testing.T) {
if err := os.MkdirAll(profileDir, 0o700); err != nil {
t.Fatal(err)
}
beltModelPins(t, profileDir, map[string]string{
beltProfileModels(t, profileDir, map[string]string{
config.KeyTierWorkerModel: "vendor/profile-worker",
config.KeyTierHighModel: "vendor/profile-careful",
config.KeyTierMastermindModel: "vendor/profile-thinking",
Expand Down Expand Up @@ -846,3 +846,33 @@ func TestDoOnTheRunEngineSeatsAnUnpinnedCheckOnTheCrewsChecker(t *testing.T) {

// bound is a named slot count for a request, the way the flag would name one.
func bound(n int) *int { return &n }

// assertBeltMachineGateDisabled ensures model overrides retain the scripted
// fixture's isolation from the host's real load and memory.
func assertBeltMachineGateDisabled(t *testing.T, profile string) {
t.Helper()
settings := config.NewSettings(config.SettingsOptions{ProfileDir: profile})
for _, key := range []string{config.KeyTaskMaxLoad, config.KeyTaskMinFreeMB} {
row, ok := settings.Row(key)
if !ok || row.Value() != "0" {
t.Fatalf("model overrides lost fixture setting %s: got %q, want 0", key, row.Value())
}
}
}

// beltProfileModels changes only the model rows: replacing the profile file
// would silently restore machine limits that beltRunEnv already disabled.
func beltProfileModels(t *testing.T, profile string, models map[string]string) {
t.Helper()
settings := config.NewSettings(config.SettingsOptions{ProfileDir: profile})
for key, model := range models {
row, ok := settings.Row(key)
if !ok {
t.Fatalf("the %s row is absent", key)
}
if err := row.Apply(model); err != nil {
t.Fatalf("set %s: %v", key, err)
}
}
assertBeltMachineGateDisabled(t, profile)
}
12 changes: 8 additions & 4 deletions cmd/codeaf/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1099,11 +1099,15 @@ func emit(graph *plan.Graph, output string, asJSON bool) error {
// lines, the environment included — for the sake of one missing quoted string,
// and the one line that mattered scrolled off the top of the terminal.
func readText(name string, args []string) (string, error) {
if len(args) == 1 && args[0] == "-" {
return readPipedText(name)
}
if len(args) > 0 {
return strings.TrimSpace(strings.Join(args, " ")), nil
text := strings.TrimSpace(strings.Join(args, " "))
if text == "" {
return "", noGoalGiven(name)
}
if len(args) == 1 && args[0] == "-" {
return readPipedText(name)
}
return text, nil
}
if stdinIsTerminal(os.Stdin) {
return "", noGoalGiven(name)
Expand Down
6 changes: 5 additions & 1 deletion docs/STANDING-ORDERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@ opened — words as the epigraph, brief as the mechanism.

**D3 — Grant.** One prose sentence on `Item`: what acting on this order may do
without asking. Empty means say-only (every pre-existing item). Wave 1 stores
and displays it; wave 3's judgment is bounded by it.
and displays it; wave 3's judgment is bounded by it. A task's separate
`Does.Isolate` setting selects a Git worktree and is displayed before approval.
The grant is permission prose, not an execution-mode parser. Each isolated
firing keeps its branch, working directory and recovery record, including
uncommitted files. See the chat manual's scheduled-branch section for limits.

**D4 — Exceptions.** `[]Exception` on `Item`, each naming exactly one
workspace OR one session. Made by the person only, from either direction (the
Expand Down
9 changes: 9 additions & 0 deletions docs/changes/unreleased/1500-traffic-age-and-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
kind: added
title: a Traffic row shows how long ago it happened, and a press opens that message
pr: 1500
surface: [chat, docs]
invalidates:
- "A Traffic row had no age on it (it was on the hint line only) and only a press on a handle did anything. Each row now ends with a dim age, and a press anywhere on the row opens the conversation the message belongs to, at that message."
- "Jumping to a completed team post could locate its entry while leaving it hidden inside collapsed activity. A deliberate Traffic jump now opens the enclosing activity and call groups before scrolling; other history stays collapsed."
---
6 changes: 6 additions & 0 deletions docs/changes/unreleased/1503-traffic-nits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
kind: fixed
title: a reminder's time reads with a middle dot, and Traffic ages stay short past a month
pr: 1503
surface: [chat]
---
8 changes: 8 additions & 0 deletions docs/changes/unreleased/1560-standing-branch-isolation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
kind: fixed
title: standing execution enforces git branch isolation and worktree validation
pr: 1560
surface: [engine]
invalidates:
- "Standing task firings claiming branch isolation or granted permission only for branch commits could execute git commits directly onto the host workspace branch. The approved does.isolate setting now selects a dedicated Git branch and worktree. Permission and reply prose no longer decide isolation. Uncommitted work and its recovery record are retained. An unchanged isolated firing reports no changes instead of a landing; its retained copy is recorded before worker initialization so failed startup cannot lose its recovery identity. Isolated tasks cannot bypass the scheduled worktree through an ordinary-turn Once answer."
---
10 changes: 10 additions & 0 deletions docs/changes/unreleased/1596-standing-scoping-budget-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
kind: fixed
title: standing order project scoping normalization, live rail allowance words, and task activity labels
pr: 1596
surface: [chat, engine]
invalidates:
- "Standing orders with project altitude previously failed workspace equality checks when comparing cleaned and uncleaned paths. Path cleaning is now normalized for project-scoped orders."
- "Standing proposal cards previously quoted stale default budget allowances. The engine now resolves each proposal against the current daily spend rail. Rendering quotes that snapshot without disk reads or parsing display text; explicitly named limits retain their words."
- "Standing card history rows previously displayed 'said:' for task action firings. They now display 'task:' for task executions."
---
10 changes: 10 additions & 0 deletions docs/changes/unreleased/1604-blank-brief-extraction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
kind: fixed
title: blank terminal briefs stop before planning or model work
pr: 1604
surface: [engine, docs]
invalidates:
- "An empty quoted brief could previously start model work with no goal. Empty and whitespace-only briefs are now rejected at the shared text-input boundary before planning, execution, or saved-plan creation."
---

Focused extraction for issue #1566. No other broad audit behavior is included.
9 changes: 9 additions & 0 deletions docs/changes/unreleased/1612-standing-once-handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
kind: fixed
title: one-time standing approvals preserve the action and report approval truthfully
pr: 1612
surface: [chat, engine]
invalidates:
- "Choosing Only now previously settled the card as done before work ran and returned a generic instruction. It now records approval without completion and hands the full approved action back with an explicit pending execution state."
- "A one-time scheduled task previously used reminder labels. Its card now says Run it then and describes running work; say-only reminders keep their existing wording."
---
4 changes: 4 additions & 0 deletions docs/changes/unreleased/1619-task-recovery-focused.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ does not promise exactly-once replay of arbitrary external operations.
Graph and run admission read current persisted limits when created and follow
later changes from another process, including the ordinary default profile.
Absent settings preserve the supplied startup limits.

Recovered tasks now retain their accepted crew pins, fallback history and spend
ceilings/tallies. Old records without that policy, or an unresolved model call,
stay interrupted instead of silently rerouting or resetting a spending limit.
8 changes: 8 additions & 0 deletions docs/changes/unreleased/1629-home-task-target.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
kind: fixed
title: Home tasks keep the project displayed before submission
pr: 1629
surface: [chat]
invalidates:
- "A task typed on Home could follow another project's newer conversation after the command cleared its draft. Slash commands now capture the displayed project before rebuilding Home, sharing the ordinary message opening path."
---
29 changes: 29 additions & 0 deletions docs/changes/unreleased/1632-reviewed-workflow-fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
kind: fixed
title: Home tasks, standing work, and traffic keep their context and navigation
pr: 1632
surface: [chat, engine]
---

Home task drafts bind to the project currently displayed. Standing work respects
project scope, shows its allowance and activity, and hands off an approved
one-time run without accidentally creating a recurring schedule. Explicit branch
isolation preserves unfinished changes in the worker copy, while ordinary
one-time work continues in place. Standing timers have a single owner and
approval receipts reflect whether scheduling succeeded. Empty extracted briefs
are rejected before execution.

Traffic rows show compact ages and open their exact message, including completed
work hidden inside a collapsed group. Reminder labels separate their cadence
from their title. Unknown timestamps remain absent.

Held tasks now notice changed machine limits and retain their accepted request across
engine restarts, reusing the focused recovery fix from #1619. A persistent engine
restart also retires old reply streams, so a follow-up no longer disappears when
its new stream number matches a completed reply from the previous engine.

Held tasks follow changed admission limits and resume with their accepted folder,
crew pins, fallback history, and spending limits after a restart. Records without
complete recovery policy or with unresolved model calls remain interrupted. A
reopened conversation replaces stale connection streams when its owner changes,
so new replies and replay cursors belong to the current session.
40 changes: 26 additions & 14 deletions docs/design/conversations-and-teams/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,19 +379,31 @@ them.
(`+ /task`, standing, jobs, `ctrl+. earlier`) and a run's plan rows stay.
- **Traffic in a manager's chat is work**: one row per thread (`teams.Threads`), and every row
reads `from → to words`. The manager is `◆`, several recipients are `@scrape +2`, and the
words follow (`◆ → @scrape +2 Please provide a st… ▸`). The state its answers leave it in
and its message count give way to the words when the column is narrow; the hint says them.
The age is never on the row, at any width: the hint line says it before its click, and the
band says it the same way, so the arrow and the names keep their cells. A narrow column cuts
only the words, at a word, with `…`. A band row is `? @model → ◆ keep the old schema?`,
amber, and a task row in the band is still cut at a clause, never leaving ` · …`. `▸`
lays the replies open as `↳ @model → ◆ ✓ done, 3 files changed` (events folded into the
member's line, the clock on the hint), and every unthreaded line under one `General` thread,
its open lines in the same `from → to`. A thin `new` line
marks what arrived since the Traffic was last in front and holds still while it is read. A
handle opens its member at the message; the rest of a row brings the message into view in
the chat in front. **In a member's chat** it is the messages to or from that member, or to
everyone, one line each, and that member is `you` (`◆ → you`, `you → ◆`, `you → @gravity`).
words follow, and how long ago at the right (`◆ → @scrape +2 Please provide a st… ▸ 2m`).
The age is `now`, `2m`, `3h`, `1d`, the same ladder a task row and a home session use
(`sinceAt`) through a day, dim, on every kind of row: a thread, a `↳` reply, a band question, General,
and a member's own lines. Past thirty days a task row and a home session print a date
(`sinceAt`). A Traffic row stays compact (`trafficAgeAt`): `30d`, weeks from six weeks
(`6w`, `12w` at ninety days), then years (`1y` at four hundred days). It moves when the minute in the row cache moves, and nowhere
else. The state its answers leave it in and its message count give way to the words when
the column is narrow; the hint says them. The arrow and the names keep their cells, then
the age, and a narrow column cuts only the words, at a word, with `…`. A band row is
`? @model → ◆ keep the old schema? 3m`, amber on the question and dim on the age, and a
task row in the band is still cut at a clause, never leaving ` · …`. `▸` lays the replies
open as `↳ @model → ◆ ✓ done, 3 files changed 4m` (events folded into the member's line,
the age on the row), and every unthreaded line under one `General` thread, its open lines
in the same `from → to` with the same age. `▸` and `▾` stay the expand door. The rest of
the row is the jump. A thin `new` line marks what arrived since the Traffic was last in
front and holds still while it is read. A handle opens its member at the message. A press
anywhere else on the row opens the conversation the message belongs to, at that message,
lifted the way a jump already lifts one: a message the sender wrote opens the sender's
chat (`◆ → all` opens the manager at the directive, `you → ◆` in a member's chat scrolls
that chat), and a message to the person opens the manager's chat. Already in front, it
scrolls in place. It does not take the keyboard and it does not open a new window. The
hint is `Open ◆'s message · 2m ago · click`. The hover ground is the whole row, padding
included. **In a member's chat** it is the messages to or from that member, or to
everyone, one line each, and that member is `you` (`◆ → you 2m`, `you → ◆ now`,
`you → @gravity 3h`).
- **Geometry.** The column is a quarter of the frame, 28 to 40 columns (30 at 120), from 100
columns up while the conversation keeps 56; `alt+w` adds 16 from 120 up. It is the same in
both views and every kind of chat, so switching, folding, the band and new rows never move
Expand Down Expand Up @@ -1518,7 +1530,7 @@ depth block is not shown and the store's own `SetParent` is the only check.

A proposal card names its kind on the first line, then what it does, then when and what one time costs. The words live in `session.StandingOptions` so the conversation, home, `--host` and the recorded `labels` say the same thing.

- A reminder (`when.at`): `wants to remind you`. `Remind me <when>`, `Change…`, `Don't remind me`. No once.
- A reminder (`when.at`): `wants to remind you`. `Remind me <when>`, `Change…`, `Don't remind me`. No once. A distance from now is said back with the clock it landed on, joined by a middle dot: `Remind me in 1 minute · 07:35`.
- A repeating check (`when.every`): `wants to set up a repeating check`. `Set it up · <cadence>`, `Change…`, `Only now, don't repeat`, `Don't set it up`.
- A watch (file, idle, probe): `wants to watch for something`. `Watch for it`, `Change…`, `Check once now`, `Don't watch`.
- A rule (`when.hold`): `wants to keep a rule`. `Keep this rule`, `Change where…`, `Don't keep it`. No once.
Expand Down
2 changes: 1 addition & 1 deletion internal/manual/chat/asking-from-home.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ on home says `? waiting on you` for as long as it does.

**The card stays after you answer it.** It does not disappear — it settles in place, greys
out, and its bottom edge carries what was decided in the same words a card in a conversation
uses: `Set it up · Mondays at 9am · set up`, `Only now, don't repeat · done now, nothing kept`,
uses: `Set it up · Mondays at 9am · set up`, `Only now, don't repeat · approved once, not scheduled`,
`Change… · you asked for something different`,
`not set up`, `ended · nothing was set up`. The answers go, so `1`, `3`, `0` and `o` are
ordinary characters again and can be typed into a follow-up. The only card that ever
Expand Down
4 changes: 2 additions & 2 deletions internal/manual/chat/conversations-and-teams.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ place on the tab strip is the manager's, pinned at the left: a quiet `+ Manager`
one and `◆ Manager` after; `◆ Make this harbor's manager` in the team switcher or in a tile's
Teams list makes an existing conversation the manager. The right-hand
column of a chat in a team has two words, `Tasks` and `Traffic` (what passes in the team). A
Traffic row reads who it is from and who it is for, `◆ → @scrape +2 Please provide…`, and in
a member's chat that member is `you` (`◆ → you`, `you → ◆`). The
Traffic row reads who it is from and who it is for, then how long ago, `◆ → @scrape +2 Please provide… 2m`, and in
a member's chat that member is `you` (`◆ → you`, `you → ◆`). A press on the row opens that message in the chat it belongs to. The
manager's opens on the Traffic, a member's on its tasks, `←` `→` switch them while the column has
the keyboard, `alt+l` shows or hides it, and `alt+m` goes to the manager. What a manager can do, and how members talk to each other, is on the
**team manager** page. The **teams page** (`/teams`, `alt+2`) lists every team as a tree
Expand Down
Loading
Loading