@cluesmith/codev 3.3.3 → 3.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard-dist/assets/index-BuflRUi6.js +220 -0
- package/dashboard-dist/assets/index-BuflRUi6.js.map +1 -0
- package/dashboard-dist/assets/index-r3bZzLmX.css +32 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +48 -0
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/ide.d.ts +20 -0
- package/dist/agent-farm/commands/ide.d.ts.map +1 -0
- package/dist/agent-farm/commands/ide.js +138 -0
- package/dist/agent-farm/commands/ide.js.map +1 -0
- package/dist/agent-farm/commands/inbox.d.ts.map +1 -1
- package/dist/agent-farm/commands/inbox.js +15 -3
- package/dist/agent-farm/commands/inbox.js.map +1 -1
- package/dist/agent-farm/commands/send.d.ts +3 -2
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +40 -6
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +28 -9
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/tower.d.ts +21 -9
- package/dist/agent-farm/commands/tower.d.ts.map +1 -1
- package/dist/agent-farm/commands/tower.js +90 -30
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/db/tower-owner.d.ts +168 -0
- package/dist/agent-farm/db/tower-owner.d.ts.map +1 -0
- package/dist/agent-farm/db/tower-owner.js +369 -0
- package/dist/agent-farm/db/tower-owner.js.map +1 -0
- package/dist/agent-farm/db/types.d.ts +30 -5
- package/dist/agent-farm/db/types.d.ts.map +1 -1
- package/dist/agent-farm/db/types.js.map +1 -1
- package/dist/agent-farm/lib/ide-record.d.ts +65 -0
- package/dist/agent-farm/lib/ide-record.d.ts.map +1 -0
- package/dist/agent-farm/lib/ide-record.js +118 -0
- package/dist/agent-farm/lib/ide-record.js.map +1 -0
- package/dist/agent-farm/lib/tunnel-client.d.ts +22 -0
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +53 -5
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/decisions/file.d.ts +50 -0
- package/dist/agent-farm/servers/decisions/file.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/file.js +146 -0
- package/dist/agent-farm/servers/decisions/file.js.map +1 -0
- package/dist/agent-farm/servers/decisions/grammar.d.ts +36 -0
- package/dist/agent-farm/servers/decisions/grammar.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/grammar.js +109 -0
- package/dist/agent-farm/servers/decisions/grammar.js.map +1 -0
- package/dist/agent-farm/servers/decisions/notice.d.ts +11 -0
- package/dist/agent-farm/servers/decisions/notice.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/notice.js +18 -0
- package/dist/agent-farm/servers/decisions/notice.js.map +1 -0
- package/dist/agent-farm/servers/decisions/parse.d.ts +36 -0
- package/dist/agent-farm/servers/decisions/parse.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/parse.js +308 -0
- package/dist/agent-farm/servers/decisions/parse.js.map +1 -0
- package/dist/agent-farm/servers/decisions/routes.d.ts +17 -0
- package/dist/agent-farm/servers/decisions/routes.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/routes.js +160 -0
- package/dist/agent-farm/servers/decisions/routes.js.map +1 -0
- package/dist/agent-farm/servers/decisions/splice.d.ts +26 -0
- package/dist/agent-farm/servers/decisions/splice.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/splice.js +120 -0
- package/dist/agent-farm/servers/decisions/splice.js.map +1 -0
- package/dist/agent-farm/servers/decisions/stamp.d.ts +4 -0
- package/dist/agent-farm/servers/decisions/stamp.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/stamp.js +171 -0
- package/dist/agent-farm/servers/decisions/stamp.js.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts +23 -2
- package/dist/agent-farm/servers/gate-profiles.d.ts.map +1 -1
- package/dist/agent-farm/servers/gate-profiles.js +43 -2
- package/dist/agent-farm/servers/gate-profiles.js.map +1 -1
- package/dist/agent-farm/servers/ide-forward.d.ts +62 -0
- package/dist/agent-farm/servers/ide-forward.d.ts.map +1 -0
- package/dist/agent-farm/servers/ide-forward.js +274 -0
- package/dist/agent-farm/servers/ide-forward.js.map +1 -0
- package/dist/agent-farm/servers/ide-server.d.ts +68 -0
- package/dist/agent-farm/servers/ide-server.d.ts.map +1 -0
- package/dist/agent-farm/servers/ide-server.js +281 -0
- package/dist/agent-farm/servers/ide-server.js.map +1 -0
- package/dist/agent-farm/servers/mailbox-delivery.d.ts +213 -4
- package/dist/agent-farm/servers/mailbox-delivery.d.ts.map +1 -1
- package/dist/agent-farm/servers/mailbox-delivery.js +489 -68
- package/dist/agent-farm/servers/mailbox-delivery.js.map +1 -1
- package/dist/agent-farm/servers/mailbox-wiring.d.ts +18 -4
- package/dist/agent-farm/servers/mailbox-wiring.d.ts.map +1 -1
- package/dist/agent-farm/servers/mailbox-wiring.js +94 -21
- package/dist/agent-farm/servers/mailbox-wiring.js.map +1 -1
- package/dist/agent-farm/servers/message-write.d.ts +138 -11
- package/dist/agent-farm/servers/message-write.d.ts.map +1 -1
- package/dist/agent-farm/servers/message-write.js +144 -35
- package/dist/agent-farm/servers/message-write.js.map +1 -1
- package/dist/agent-farm/servers/overview.d.ts +32 -15
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +181 -103
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/render-gate.d.ts +53 -0
- package/dist/agent-farm/servers/render-gate.d.ts.map +1 -1
- package/dist/agent-farm/servers/render-gate.js +135 -24
- package/dist/agent-farm/servers/render-gate.js.map +1 -1
- package/dist/agent-farm/servers/session-submit.d.ts +7 -4
- package/dist/agent-farm/servers/session-submit.d.ts.map +1 -1
- package/dist/agent-farm/servers/session-submit.js +7 -4
- package/dist/agent-farm/servers/session-submit.js.map +1 -1
- package/dist/agent-farm/servers/tower-cron.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-cron.js +4 -1
- package/dist/agent-farm/servers/tower-cron.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +6 -7
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +116 -18
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +64 -7
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +53 -8
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.js +18 -1
- package/dist/agent-farm/servers/tower-websocket.js.map +1 -1
- package/dist/agent-farm/utils/message-format.d.ts +8 -0
- package/dist/agent-farm/utils/message-format.d.ts.map +1 -1
- package/dist/agent-farm/utils/message-format.js +21 -6
- package/dist/agent-farm/utils/message-format.js.map +1 -1
- package/dist/agent-farm/utils/port.d.ts +22 -0
- package/dist/agent-farm/utils/port.d.ts.map +1 -0
- package/dist/agent-farm/utils/port.js +35 -0
- package/dist/agent-farm/utils/port.js.map +1 -0
- package/dist/agent-farm/utils/server-utils.d.ts +26 -0
- package/dist/agent-farm/utils/server-utils.d.ts.map +1 -1
- package/dist/agent-farm/utils/server-utils.js +36 -0
- package/dist/agent-farm/utils/server-utils.js.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/consult/index.d.ts +20 -1
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +117 -3
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/consult/tree-tripwire.d.ts +177 -0
- package/dist/commands/consult/tree-tripwire.d.ts.map +1 -0
- package/dist/commands/consult/tree-tripwire.js +356 -0
- package/dist/commands/consult/tree-tripwire.js.map +1 -0
- package/dist/commands/doctor.d.ts +69 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +163 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/generate-image.d.ts +5 -0
- package/dist/commands/generate-image.d.ts.map +1 -1
- package/dist/commands/generate-image.js +225 -4
- package/dist/commands/generate-image.js.map +1 -1
- package/dist/commands/porch/checks.d.ts +7 -1
- package/dist/commands/porch/checks.d.ts.map +1 -1
- package/dist/commands/porch/checks.js +77 -14
- package/dist/commands/porch/checks.js.map +1 -1
- package/dist/commands/porch/index.d.ts +38 -1
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +79 -43
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/protocol.d.ts +4 -3
- package/dist/commands/porch/protocol.d.ts.map +1 -1
- package/dist/commands/porch/protocol.js +32 -5
- package/dist/commands/porch/protocol.js.map +1 -1
- package/dist/commands/porch/types.d.ts +2 -0
- package/dist/commands/porch/types.d.ts.map +1 -1
- package/dist/lib/agent-env.d.ts +95 -0
- package/dist/lib/agent-env.d.ts.map +1 -0
- package/dist/lib/agent-env.js +137 -0
- package/dist/lib/agent-env.js.map +1 -0
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/forge-contracts.d.ts +10 -0
- package/dist/lib/forge-contracts.d.ts.map +1 -1
- package/dist/lib/forge-contracts.js.map +1 -1
- package/dist/lib/forge-rate-limit.d.ts +45 -0
- package/dist/lib/forge-rate-limit.d.ts.map +1 -0
- package/dist/lib/forge-rate-limit.js +89 -0
- package/dist/lib/forge-rate-limit.js.map +1 -0
- package/dist/lib/forge.d.ts +28 -0
- package/dist/lib/forge.d.ts.map +1 -1
- package/dist/lib/forge.js +63 -10
- package/dist/lib/forge.js.map +1 -1
- package/dist/lib/github.d.ts +13 -1
- package/dist/lib/github.d.ts.map +1 -1
- package/dist/lib/github.js +58 -15
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/test-env.d.ts +17 -0
- package/dist/lib/test-env.d.ts.map +1 -1
- package/dist/lib/test-env.js +20 -0
- package/dist/lib/test-env.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +122 -4
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +142 -7
- package/dist/terminal/pty-session.js.map +1 -1
- package/dist/terminal/session-manager.d.ts +23 -2
- package/dist/terminal/session-manager.d.ts.map +1 -1
- package/dist/terminal/session-manager.js +115 -36
- package/dist/terminal/session-manager.js.map +1 -1
- package/dist/terminal/session-screen.d.ts +34 -5
- package/dist/terminal/session-screen.d.ts.map +1 -1
- package/dist/terminal/session-screen.js +52 -6
- package/dist/terminal/session-screen.js.map +1 -1
- package/dist/terminal/terminal-replies.d.ts +102 -0
- package/dist/terminal/terminal-replies.d.ts.map +1 -0
- package/dist/terminal/terminal-replies.js +181 -0
- package/dist/terminal/terminal-replies.js.map +1 -0
- package/package.json +4 -4
- package/scripts/forge/github/pr-list.sh +6 -2
- package/scripts/forge/github/pr-search.sh +4 -2
- package/scripts/forge/gitlab/issue-search.sh +1 -0
- package/scripts/forge/gitlab/pr-search.sh +35 -2
- package/scripts/forge/linear/auth-status.sh +1 -0
- package/scripts/forge/linear/issue-comment.sh +1 -0
- package/scripts/forge/linear/issue-list.sh +1 -0
- package/scripts/forge/linear/issue-search.sh +1 -0
- package/scripts/forge/linear/issue-view.sh +1 -0
- package/scripts/forge/linear/recently-closed.sh +1 -0
- package/scripts/forge/linear/user-identity.sh +1 -0
- package/skeleton/.claude/skills/afx/SKILL.md +15 -0
- package/skeleton/.claude/skills/arch-init/SKILL.md +56 -9
- package/skeleton/.claude/skills/arch-save/SKILL.md +100 -9
- package/skeleton/.claude/skills/consult/SKILL.md +9 -0
- package/skeleton/.claude/skills/generate-image/SKILL.md +19 -2
- package/skeleton/.claude/skills/porch/SKILL.md +18 -0
- package/skeleton/.codex/skills/afx/SKILL.md +15 -0
- package/skeleton/.codex/skills/arch-init/SKILL.md +56 -9
- package/skeleton/.codex/skills/arch-save/SKILL.md +100 -9
- package/skeleton/.codex/skills/consult/SKILL.md +9 -0
- package/skeleton/.codex/skills/generate-image/SKILL.md +19 -2
- package/skeleton/.codex/skills/porch/SKILL.md +18 -0
- package/skeleton/protocol-schema.json +6 -0
- package/skeleton/protocols/maintain/protocol.md +5 -0
- package/skeleton/protocols/pir/prompts/review.md +0 -1
- package/skeleton/protocols/protocol-schema.json +6 -0
- package/skeleton/resources/commands/agent-farm.md +71 -2
- package/skeleton/resources/commands/consult.md +9 -2
- package/skeleton/roles/consultant.md +32 -0
- package/skeleton/templates/AGENTS.md +1 -1
- package/skeleton/templates/CLAUDE.md +1 -1
- package/skeleton/templates/cheatsheet.md +1 -1
- package/dashboard-dist/assets/index-CUIjS_Vb.js +0 -199
- package/dashboard-dist/assets/index-CUIjS_Vb.js.map +0 -1
- package/dashboard-dist/assets/index-DnYLy5C_.css +0 -32
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: generate-image
|
|
3
|
-
description: AI image generation via Gemini
|
|
3
|
+
description: AI image generation via Gemini with optional async providers. Use when the user wants to generate, create, or make an image, or when you need to create visual assets like logos, diagrams, or illustrations. Requires the API key for the selected provider.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# generate-image - AI Image Generation
|
|
@@ -22,7 +22,7 @@ Note: this is a `codev` subcommand, not standalone.
|
|
|
22
22
|
-r, --resolution <res> Resolution: 1K, 2K, 4K (default: 1K)
|
|
23
23
|
-a, --aspect <ratio> Aspect ratio (default: 1:1)
|
|
24
24
|
--ref <image> Reference image (repeatable, max 14)
|
|
25
|
-
-p, --provider <name> Provider
|
|
25
|
+
-p, --provider <name> Provider name (default: gemini)
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
## Aspect ratios
|
|
@@ -64,3 +64,20 @@ Measured differences on that path:
|
|
|
64
64
|
than silently ignoring the images.
|
|
65
65
|
- The model returns JPEG, so the output file is named after its actual bytes
|
|
66
66
|
instead of writing JPEG into the default `output.png`.
|
|
67
|
+
|
|
68
|
+
## MuAPI provider
|
|
69
|
+
|
|
70
|
+
`-p muapi` uses MuAPI's Nano Banana Pro endpoint with the same aspect-ratio and
|
|
71
|
+
resolution controls. Set `MUAPI_API_KEY` (or `MU_API_KEY`) using the [MuAPI
|
|
72
|
+
access keys page](https://muapi.ai/access-keys). Reference images are uploaded
|
|
73
|
+
to MuAPI and sent to the edit endpoint; returned media is downloaded only over
|
|
74
|
+
HTTPS.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
codev generate-image "A sunset over mountains" -p muapi -a 16:9
|
|
78
|
+
codev generate-image "Keep the subject, change the lighting" -p muapi --ref subject.png
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The provider submits a job, polls the [MuAPI image API](https://muapi.ai/ai-image-api),
|
|
82
|
+
and writes the returned image locally. Polling and individual requests are
|
|
83
|
+
bounded, and the API key is never sent to the returned media host.
|
|
@@ -45,6 +45,7 @@ porch approve 42 pr --a-human-explicitly-approved-this
|
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
47
|
porch pending # List all gates waiting for approval
|
|
48
|
+
porch pending --all # Include stale records on finished/advanced projects (hidden by default)
|
|
48
49
|
```
|
|
49
50
|
|
|
50
51
|
## Critical rules
|
|
@@ -55,6 +56,23 @@ porch pending # List all gates waiting for approval
|
|
|
55
56
|
- `porch run` is for strict mode only — soft mode builders follow the protocol document manually
|
|
56
57
|
- When running `porch approve` from the architect, use a subshell if you need worktree context: `(cd /path/to/worktree && porch approve ...)`
|
|
57
58
|
|
|
59
|
+
## Check overrides and timeouts (`porch.checks`)
|
|
60
|
+
|
|
61
|
+
Override a protocol check per name in `.codev/config.json` under `porch.checks` instead of forking `protocol.json`. Each entry takes `command` (replace), `cwd` (replace), `timeout_ms` (replace), and/or `skip: true`:
|
|
62
|
+
|
|
63
|
+
```jsonc
|
|
64
|
+
{
|
|
65
|
+
"porch": {
|
|
66
|
+
"checks": {
|
|
67
|
+
"tests": { "command": "uv run pytest", "timeout_ms": 900000 },
|
|
68
|
+
"e2e_tests": { "skip": true }
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
A phase check is killed after 5 minutes unless it sets `timeout_ms` — in `protocol.json` or in its `porch.checks` override. On timeout porch kills the check's whole process tree.
|
|
75
|
+
|
|
58
76
|
## State storage
|
|
59
77
|
|
|
60
78
|
Project state lives in `codev/projects/<id>-<name>/status.yaml`, managed automatically by porch. The status file tracks current phase, gate states, consultation results, and timestamps.
|
|
@@ -184,8 +184,23 @@ There is NO `afx tower restart` — use `afx tower stop && afx tower start`.
|
|
|
184
184
|
```bash
|
|
185
185
|
afx workspace start # Start workspace for current project
|
|
186
186
|
afx workspace stop # Stop workspace processes
|
|
187
|
+
afx workspace add-architect --name <name> # Add a named sibling architect terminal
|
|
188
|
+
afx workspace remove-architect <name> # Remove a sibling architect (cannot remove main)
|
|
189
|
+
afx workspace recover # Revive builders whose shellper died (e.g. after reboot)
|
|
187
190
|
```
|
|
188
191
|
|
|
192
|
+
**Recreating a dead architect** (its process died while Tower kept the registration):
|
|
193
|
+
re-add it under the SAME name, then re-init its identity:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
afx workspace add-architect --name <name>
|
|
197
|
+
afx send architect:<name> "/arch-init <name>"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Builder-to-architect affinity survives the death (builders keep their Owner), so a
|
|
201
|
+
same-name re-add restores routing with no worktree impact and no builder disruption.
|
|
202
|
+
`afx workspace recover` revives builders only, not architects.
|
|
203
|
+
|
|
189
204
|
`afx dash` is a deprecated alias — use `afx workspace` instead.
|
|
190
205
|
|
|
191
206
|
## afx cron
|
|
@@ -46,12 +46,56 @@ name in a multi-architect workspace).
|
|
|
46
46
|
(`codev/state/*.md`); never commit them. Builder `*_thread.md` files
|
|
47
47
|
are the opposite: versioned, shipping with each builder PR.
|
|
48
48
|
|
|
49
|
-
3. **Confirm identity + orient
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
3. **Confirm identity + orient.** In one tight block, report: who you now are
|
|
50
|
+
(name + one-line role from the banner, if present), the file you read, and
|
|
51
|
+
the current-state / open-loops summary from the most recent dated section
|
|
52
|
+
(or the file's leading content if it has no dated sections). If the banner
|
|
53
|
+
carries a `NEXT TASK` line, report both halves of it, as
|
|
54
|
+
`Next task from the owner at save time: <verbatim> → resolved: <gloss>`
|
|
55
|
+
(omit `→ resolved: …` when the line carries no `[resolved at save: …]` gloss).
|
|
56
|
+
|
|
57
|
+
4. **Start on the next task, if the banner carries one.** It is the **first
|
|
58
|
+
action of the resumed session**, ahead of the general resume agenda — the
|
|
59
|
+
owner wrote it at save time precisely so it would not have to be typed
|
|
60
|
+
again once you came back. Begin it without waiting for a further prompt.
|
|
61
|
+
- It carries the owner's authority the way any owner message does, **with
|
|
62
|
+
the standard limits unchanged**. A next task never by itself approves a
|
|
63
|
+
porch gate, merges a PR, cuts a release, restarts Tower, or performs any
|
|
64
|
+
other act that needs a per-occasion word. If the next task *is* such an
|
|
65
|
+
act, prepare it and ask for the word live: a saved instruction is an
|
|
66
|
+
instruction, not a pre-spent approval.
|
|
67
|
+
- **The gloss carries the word — for the items it names, and only them.**
|
|
68
|
+
Items named in a `[resolved at save: …]` gloss are approved for the act
|
|
69
|
+
the owner's words name: "merge them all [resolved at save: PRs #1710,
|
|
70
|
+
#1712]" means merge #1710 and #1712 without asking again. The owner gave
|
|
71
|
+
the word at save time, and the saving session pinned it to those items.
|
|
72
|
+
This narrows the rule above; it does not remove it — and a line with no
|
|
73
|
+
gloss pre-approves nothing:
|
|
74
|
+
- The act must be the one the owner's words say. **A gloss never widens
|
|
75
|
+
the verb** — "merge" does not also approve a release.
|
|
76
|
+
- **Anything not in the gloss still needs the word live.** A PR that
|
|
77
|
+
appeared after the save, an item the gloss did not name, a gate the
|
|
78
|
+
words did not mention → prepare and ask, exactly as above.
|
|
79
|
+
- Porch gates are still relayed to the builder, never run by you: the
|
|
80
|
+
gloss lets you *relay* the approval without re-asking; it does not
|
|
81
|
+
change who runs `porch approve`.
|
|
82
|
+
- Ordinary verification still applies: an approved merge still waits for
|
|
83
|
+
green CI, and a gloss item you find already merged, closed, or changed
|
|
84
|
+
is reported, not forced.
|
|
85
|
+
- **A line marked `[carried over — …]` is orientation only.** Its gloss
|
|
86
|
+
was written by an earlier cycle and carries no word: ask for it before
|
|
87
|
+
any gated act.
|
|
88
|
+
- **This does not narrow the gate rule.** The human decision was explicit
|
|
89
|
+
at save time, and the gloss is its record. What the rule forbids —
|
|
90
|
+
inferring approval from a gate notification, from silence, or from an
|
|
91
|
+
agent's own judgment — stays forbidden; a gloss is none of those.
|
|
92
|
+
- **Once you have started, delete the `NEXT TASK` line from the banner**
|
|
93
|
+
and record the pickup as a log entry (`picked up next task: <verbatim>
|
|
94
|
+
→ resolved: <gloss>`, omitting `→ resolved: …` when there was no gloss).
|
|
95
|
+
A second re-init, or the next `/arch-save`, must not re-run it.
|
|
96
|
+
|
|
97
|
+
5. **Then follow the state file.** Carry out whatever it says to do on
|
|
98
|
+
resume. Do not invent a new agenda — resume the one the state file
|
|
55
99
|
describes.
|
|
56
100
|
|
|
57
101
|
## Saving your state (and knowing when to `/clear`)
|
|
@@ -118,9 +162,12 @@ Do not repeat it, and do not prompt for it at any other time.
|
|
|
118
162
|
**`/arch-save` packages this whole loop**, and is the preferred path when the
|
|
119
163
|
owner directs a refresh: it stops your monitors, writes the pruned state file,
|
|
120
164
|
clears, and schedules `/arch-init` to bring you back — in that order, which is
|
|
121
|
-
the part that matters.
|
|
122
|
-
|
|
123
|
-
|
|
165
|
+
the part that matters. It also accepts a **next task** as free text
|
|
166
|
+
(`/arch-save file and spawn that issue`), which it writes into the banner as a
|
|
167
|
+
`NEXT TASK` line for step 4 above to pick up. The save discipline above is
|
|
168
|
+
what it performs at its step 3, so this section remains the source of truth
|
|
169
|
+
for *how to write the file*; `/arch-save` is the source of truth for *the
|
|
170
|
+
sequence*. The manual path
|
|
124
171
|
(save → human clears → `/arch-init`) stays valid and is the fallback when
|
|
125
172
|
Tower is unavailable.
|
|
126
173
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: arch-save
|
|
3
3
|
description: Save an architect's state, clear its context, and re-init automatically — the packaged save→clear→re-init refresh cycle. Use when the owner directs a context refresh, or says "/arch-save", "save and clear", "refresh your context". Runs on the owner's direction; an architect does not invoke it autonomously mid-task. Counterpart to /arch-init, which recovers the state this writes.
|
|
4
|
-
argument-hint: "[name] (e.g. main;
|
|
4
|
+
argument-hint: "[name] [next task] (e.g. main; or: file and spawn that issue)"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# /arch-save — save state, clear, and come back as yourself
|
|
@@ -9,7 +9,18 @@ argument-hint: "[name] (e.g. main; omit to auto-detect via afx whoami)"
|
|
|
9
9
|
Long sessions accumulate stale context. This is the deliberate cure: you choose the
|
|
10
10
|
moment, you choose what survives, and a fresh session resumes from what you wrote.
|
|
11
11
|
|
|
12
|
-
`$ARGUMENTS`
|
|
12
|
+
`$ARGUMENTS` carries the architect name, a **next task** for the session that comes back,
|
|
13
|
+
or both:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
/arch-save save, clear, re-init, then wait
|
|
17
|
+
/arch-save file and spawn that issue … and start on that first, unprompted
|
|
18
|
+
/arch-save main file and spawn that issue explicit name, then the next task
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The next task is how an owner who already knows what the refreshed session should do first
|
|
22
|
+
says so once, at the moment they direct the refresh, instead of watching for the re-init to
|
|
23
|
+
land and typing it again.
|
|
13
24
|
|
|
14
25
|
## When NOT to run this
|
|
15
26
|
|
|
@@ -28,20 +39,51 @@ action. A mid-task snapshot resumes into confusion.
|
|
|
28
39
|
Do these in order. **The order is the feature** — step 3 must precede step 4, because the
|
|
29
40
|
context that knows what to write is the one about to be destroyed.
|
|
30
41
|
|
|
31
|
-
### 1. Resolve your name
|
|
42
|
+
### 1. Resolve your name, then split off the next task
|
|
32
43
|
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
**Always run `afx whoami` first**, whatever `$ARGUMENTS` holds — the split below cannot
|
|
45
|
+
tell a name from a task until it knows your name. The name rules are unchanged:
|
|
35
46
|
|
|
47
|
+
- `type: architect` → the reported `name` is yours.
|
|
36
48
|
- `type: builder` → **STOP.** This terminal is a builder. Report the mismatch.
|
|
37
|
-
- Non-zero exit →
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
- Non-zero exit → you have no name yet. A single-token `$ARGUMENTS` that validates as a
|
|
50
|
+
name is still accepted as one; anything else → **STOP** and ask which architect you are.
|
|
51
|
+
Do **not** guess, and do not default to `main` — writing another architect's state file
|
|
52
|
+
is the exact failure `/arch-init` exists to prevent (#1094).
|
|
40
53
|
|
|
41
54
|
**Validate the name before building any path**: `[a-z][a-z0-9-]*`, at most 64 characters.
|
|
42
55
|
Reject slashes, `..`, uppercase, spaces. Never interpolate an unvalidated name into
|
|
43
56
|
`codev/state/<name>.md`.
|
|
44
57
|
|
|
58
|
+
Then split `$ARGUMENTS`:
|
|
59
|
+
|
|
60
|
+
1. `$ARGUMENTS` is empty → name from `afx whoami`, and there is no next task.
|
|
61
|
+
2. The **first whitespace-separated token** equals the whoami name (or, when whoami could
|
|
62
|
+
not resolve one, is a single token that validates as a name) → that token is the name,
|
|
63
|
+
and the **remainder** is the next-task text, which may be empty.
|
|
64
|
+
3. Otherwise → the **whole** of `$ARGUMENTS` is the next-task text, and the name comes
|
|
65
|
+
from `afx whoami`.
|
|
66
|
+
|
|
67
|
+
So `/arch-save` and `/arch-save main` behave exactly as they always have. The one
|
|
68
|
+
ambiguity — a next task whose first word happens to be your own architect name — is
|
|
69
|
+
accepted rather than worked around: lead with the explicit name
|
|
70
|
+
(`/arch-save main main is stalled, look at it`) to disambiguate.
|
|
71
|
+
|
|
72
|
+
**If you had to ask which architect you are, the next task still stands.** The answer
|
|
73
|
+
supplies the name; `$ARGUMENTS` already supplied the task. Do not make the owner retype it.
|
|
74
|
+
|
|
75
|
+
**Guard, applied after the split: a leading token that names a *different* architect stops
|
|
76
|
+
you.** If the first token validates as a name, differs from the name whoami reported, and
|
|
77
|
+
`codev/state/<token>.md` exists → **STOP and ask which architect you are. Write nothing.**
|
|
78
|
+
whoami can be wrong (#1094), and rule 3 would otherwise bury a real name-override inside
|
|
79
|
+
next-task text and save to whoami's file; a task that merely opens with a sibling's name is
|
|
80
|
+
the only case this costs, and it costs one clarification.
|
|
81
|
+
|
|
82
|
+
**This is not how `/arch-init` resolves a name**, and the asymmetry is deliberate:
|
|
83
|
+
`/arch-init` takes no next task, so any non-empty argument there is unambiguously a name
|
|
84
|
+
and overrides whoami outright. Here the first token is weighed *against* whoami, which is
|
|
85
|
+
why the guard above exists — never save into a name you did not verify.
|
|
86
|
+
|
|
45
87
|
### 2. Stop your own monitors
|
|
46
88
|
|
|
47
89
|
Enumerate every monitor, watcher or background task you armed, and stop it.
|
|
@@ -75,6 +117,50 @@ first (`cp codev/state/<name>.md codev/state/.<name>.bak.md`) is cheap insurance
|
|
|
75
117
|
**Content guardrails.** No secrets — tokens, keys, credentials. No transcript dumps, no
|
|
76
118
|
raw tool output. Only: current focus, open loops, and what a fresh session needs to resume.
|
|
77
119
|
|
|
120
|
+
**Write the next task into the banner**, if step 1 produced one. Add a single line to the
|
|
121
|
+
banner block, directly after the `⭐ THIS /clear IS INTENTIONAL` line:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
# ⏭ NEXT TASK (owner-directed at save, 2026-09-19T02:10Z): file and spawn that issue
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- **Verbatim.** Collapse newlines to spaces; do not paraphrase, expand, or "helpfully"
|
|
128
|
+
plan it. Those are the owner's words, and the context writing them down is the one about
|
|
129
|
+
to be destroyed — this is the last moment at which a paraphrase can be caught.
|
|
130
|
+
- **New text replaces** any existing NEXT TASK line.
|
|
131
|
+
- **No new text preserves an existing one.** A NEXT TASK line still in the banner means the
|
|
132
|
+
previous cycle never came back to pick it up; dropping it silently would lose an owner
|
|
133
|
+
instruction that nothing else is holding. **Mark it carried over when you preserve it:**
|
|
134
|
+
append `[carried over — gloss orients only; re-confirm before acting]` to the line (once;
|
|
135
|
+
a line already marked stays as it is). A gloss carries the owner's word only for the
|
|
136
|
+
cycle that wrote it.
|
|
137
|
+
|
|
138
|
+
**Then resolve its referents — resolve, don't plan.** After the clear, "them" points at
|
|
139
|
+
nothing; this context is the only one that knows what the owner meant. So pin every
|
|
140
|
+
referent in the owner's words to a concrete, durable identifier, and append it to the same
|
|
141
|
+
line, after the verbatim text, as a `[resolved at save: …]` gloss:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
# ⏭ NEXT TASK (owner-directed at save, 2026-09-22T13:40Z): merge them all [resolved at save: PRs #1710, #1712, #1715]
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
- **Every referent.** Pronouns and deictics — "them", "that issue", "his PR", "the failing
|
|
148
|
+
one" — become PR numbers, issue numbers, builder ids, branch names, file paths.
|
|
149
|
+
- **Resolution only.** The gloss names *what*, never *how*: no steps, no ordering, no
|
|
150
|
+
caveats, no "after CI is green". A gloss that contains a plan has overstepped; the
|
|
151
|
+
resumed session plans.
|
|
152
|
+
- **No referents → no gloss.** `/arch-save review PR #1712` needs nothing; write the line
|
|
153
|
+
as above without one. Never add an empty or redundant gloss.
|
|
154
|
+
- **Cannot resolve → do not clear.** If any referent is ambiguous or unknown to you,
|
|
155
|
+
**stop before step 4** and ask the owner which items are meant. Clearing with an
|
|
156
|
+
unresolved task destroys the only context that could have answered. This is the one
|
|
157
|
+
case where `/arch-save` may pause its own cycle — it is cheap, and the alternative is a
|
|
158
|
+
wrong merge. Tell the owner your monitors are already stopped (step 2), and on their
|
|
159
|
+
answer resume from here: write the gloss, then continue to step 4.
|
|
160
|
+
|
|
161
|
+
The gloss is more than orientation: `/arch-init` treats the items it names as approved for
|
|
162
|
+
the act the owner's words name, so it is how the owner's word survives the clear.
|
|
163
|
+
|
|
78
164
|
Use the template at the end of this document.
|
|
79
165
|
|
|
80
166
|
### 4. Clear
|
|
@@ -160,12 +246,17 @@ literal text on the front of the next message never executes.
|
|
|
160
246
|
|
|
161
247
|
The structure below comes from a live run of this cycle. Every element earns its place;
|
|
162
248
|
keep them all, including a `MONITORS:` line even when the answer is "none armed" — an
|
|
163
|
-
omitted monitor list is indistinguishable from a forgotten one.
|
|
249
|
+
omitted monitor list is indistinguishable from a forgotten one. The `NEXT TASK` line is the
|
|
250
|
+
single exception: it appears only when there is one.
|
|
164
251
|
|
|
165
252
|
```
|
|
166
253
|
# <lane> architect — state (vNN, <date> ~HH:MM UTC — <milestone>, DELIBERATE /clear cycle)
|
|
167
254
|
# ⭐ THIS /clear IS INTENTIONAL (owner-directed context refresh). On re-init: normal
|
|
168
255
|
# /arch-init flow, then:
|
|
256
|
+
# ⏭ NEXT TASK (owner-directed at save, <ISO timestamp>): <the owner's words, verbatim> [resolved at save: <referents>]
|
|
257
|
+
# — OPTIONAL; present only when the save carried one. The `[resolved at save: …]` gloss
|
|
258
|
+
# is optional too: present only when the words had referents to resolve. /arch-init
|
|
259
|
+
# starts here before the agenda below, then deletes this line and logs the pickup.
|
|
169
260
|
# 1. MONITORS: <what to stop if it is still firing, then what to re-arm> — watch target,
|
|
170
261
|
# cadence, alert pattern. Self-test once before trusting alerts. ("none armed" is a
|
|
171
262
|
# valid and complete answer.)
|
|
@@ -24,6 +24,15 @@ The `-m` / `--model` flag is **always required** except for `consult stats`.
|
|
|
24
24
|
| `codex` | `gpt` | Thorough (~200-250s), shell exploration |
|
|
25
25
|
| `claude` | `opus` | Agent SDK with tool use (~60-120s) |
|
|
26
26
|
|
|
27
|
+
## Credentials and `.env`
|
|
28
|
+
|
|
29
|
+
`consult` loads `<workspace>/.env` and sets every key the shell does not already define, **credentials included**. Those override your stored login:
|
|
30
|
+
|
|
31
|
+
- claude: `CLAUDE_CODE_OAUTH_TOKEN` (or `ANTHROPIC_AUTH_TOKEN` / `ANTHROPIC_API_KEY`) beats the keychain login. When an OAuth token is set, the API keys are dropped.
|
|
32
|
+
- codex: `CODEX_API_KEY` beats the ChatGPT login. `OPENAI_API_KEY` is ignored.
|
|
33
|
+
|
|
34
|
+
Each SDK lane prints what it authenticates with, e.g. `[CLAUDE] auth: CLAUDE_CODE_OAUTH_TOKEN (from .env)`. If a review fails with a usage-limit or auth error while your own login works, check that line first. A key exported in the shell wins over `.env`.
|
|
35
|
+
|
|
27
36
|
## All flags
|
|
28
37
|
|
|
29
38
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: generate-image
|
|
3
|
-
description: AI image generation via Gemini
|
|
3
|
+
description: AI image generation via Gemini with optional async providers. Use when the user wants to generate, create, or make an image, or when you need to create visual assets like logos, diagrams, or illustrations. Requires the API key for the selected provider.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# generate-image - AI Image Generation
|
|
@@ -22,7 +22,7 @@ Note: this is a `codev` subcommand, not standalone.
|
|
|
22
22
|
-r, --resolution <res> Resolution: 1K, 2K, 4K (default: 1K)
|
|
23
23
|
-a, --aspect <ratio> Aspect ratio (default: 1:1)
|
|
24
24
|
--ref <image> Reference image (repeatable, max 14)
|
|
25
|
-
-p, --provider <name> Provider
|
|
25
|
+
-p, --provider <name> Provider name (default: gemini)
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
## Aspect ratios
|
|
@@ -64,3 +64,20 @@ Measured differences on that path:
|
|
|
64
64
|
than silently ignoring the images.
|
|
65
65
|
- The model returns JPEG, so the output file is named after its actual bytes
|
|
66
66
|
instead of writing JPEG into the default `output.png`.
|
|
67
|
+
|
|
68
|
+
## MuAPI provider
|
|
69
|
+
|
|
70
|
+
`-p muapi` uses MuAPI's Nano Banana Pro endpoint with the same aspect-ratio and
|
|
71
|
+
resolution controls. Set `MUAPI_API_KEY` (or `MU_API_KEY`) using the [MuAPI
|
|
72
|
+
access keys page](https://muapi.ai/access-keys). Reference images are uploaded
|
|
73
|
+
to MuAPI and sent to the edit endpoint; returned media is downloaded only over
|
|
74
|
+
HTTPS.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
codev generate-image "A sunset over mountains" -p muapi -a 16:9
|
|
78
|
+
codev generate-image "Keep the subject, change the lighting" -p muapi --ref subject.png
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The provider submits a job, polls the [MuAPI image API](https://muapi.ai/ai-image-api),
|
|
82
|
+
and writes the returned image locally. Polling and individual requests are
|
|
83
|
+
bounded, and the API key is never sent to the returned media host.
|
|
@@ -45,6 +45,7 @@ porch approve 42 pr --a-human-explicitly-approved-this
|
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
47
|
porch pending # List all gates waiting for approval
|
|
48
|
+
porch pending --all # Include stale records on finished/advanced projects (hidden by default)
|
|
48
49
|
```
|
|
49
50
|
|
|
50
51
|
## Critical rules
|
|
@@ -55,6 +56,23 @@ porch pending # List all gates waiting for approval
|
|
|
55
56
|
- `porch run` is for strict mode only — soft mode builders follow the protocol document manually
|
|
56
57
|
- When running `porch approve` from the architect, use a subshell if you need worktree context: `(cd /path/to/worktree && porch approve ...)`
|
|
57
58
|
|
|
59
|
+
## Check overrides and timeouts (`porch.checks`)
|
|
60
|
+
|
|
61
|
+
Override a protocol check per name in `.codev/config.json` under `porch.checks` instead of forking `protocol.json`. Each entry takes `command` (replace), `cwd` (replace), `timeout_ms` (replace), and/or `skip: true`:
|
|
62
|
+
|
|
63
|
+
```jsonc
|
|
64
|
+
{
|
|
65
|
+
"porch": {
|
|
66
|
+
"checks": {
|
|
67
|
+
"tests": { "command": "uv run pytest", "timeout_ms": 900000 },
|
|
68
|
+
"e2e_tests": { "skip": true }
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
A phase check is killed after 5 minutes unless it sets `timeout_ms` — in `protocol.json` or in its `porch.checks` override. On timeout porch kills the check's whole process tree.
|
|
75
|
+
|
|
58
76
|
## State storage
|
|
59
77
|
|
|
60
78
|
Project state lives in `codev/projects/<id>-<name>/status.yaml`, managed automatically by porch. The status file tracks current phase, gate states, consultation results, and timestamps.
|
|
@@ -215,6 +215,12 @@
|
|
|
215
215
|
"type": "string",
|
|
216
216
|
"description": "Human-readable description"
|
|
217
217
|
},
|
|
218
|
+
"timeout_ms": {
|
|
219
|
+
"type": "integer",
|
|
220
|
+
"description": "Kill the check after this many milliseconds (default: 300000, i.e. 5 minutes)",
|
|
221
|
+
"minimum": 1,
|
|
222
|
+
"maximum": 2147483647
|
|
223
|
+
},
|
|
218
224
|
"on_fail": {
|
|
219
225
|
"type": "string",
|
|
220
226
|
"enum": ["fail", "retry", "warn"],
|
|
@@ -7,6 +7,11 @@ Use it for dead code and unused dependencies, quarterly hygiene, pre-release cle
|
|
|
7
7
|
keeping the governance docs honest — `arch.md`/`arch-critical.md`,
|
|
8
8
|
`lessons-learned.md`/`lessons-critical.md`, and the `CLAUDE.md`↔`AGENTS.md` twins.
|
|
9
9
|
|
|
10
|
+
It is a scheduled, whole-repository run that a human asks for, scoped from the last run's base
|
|
11
|
+
commit. It is **not** the protocol for one targeted cleanup: a specific dead file, a drifted
|
|
12
|
+
document, or a stale section is an ordinary issue under BUGFIX (or AIR). Reaching for "a
|
|
13
|
+
MAINTAIN pass" to fix one thing misuses the since-marker and the audit discipline below.
|
|
14
|
+
|
|
10
15
|
## The state machine
|
|
11
16
|
|
|
12
17
|
```json
|
|
@@ -133,6 +133,12 @@
|
|
|
133
133
|
"type": "string",
|
|
134
134
|
"description": "Command to run"
|
|
135
135
|
},
|
|
136
|
+
"timeout_ms": {
|
|
137
|
+
"type": "integer",
|
|
138
|
+
"minimum": 1,
|
|
139
|
+
"maximum": 2147483647,
|
|
140
|
+
"description": "Kill the check after this many milliseconds (default: 300000, i.e. 5 minutes)"
|
|
141
|
+
},
|
|
136
142
|
"on_fail": {
|
|
137
143
|
"type": "string",
|
|
138
144
|
"description": "Action on failure: 'retry' or phase name to return to"
|
|
@@ -391,11 +391,36 @@ Sends text to a builder's terminal. Useful for:
|
|
|
391
391
|
|
|
392
392
|
- **delivered** — the message was written to the recipient's prompt after a clean render-gate pass (an empty, render-verified prompt).
|
|
393
393
|
- **held** — the prompt was not clear, so the message is persisted in Tower's durable mailbox and **delivers automatically** the moment the recipient's prompt is clean (after a submit, on output quiescence, or a poll backstop). The response carries a **why-held reason** and a mailbox id:
|
|
394
|
-
- `busy` —
|
|
394
|
+
- `busy` — the prompt is occupied. `afx inbox` qualifies it with the gate's own detail:
|
|
395
|
+
`busy:user-text` (a draft, menu, dialog, or wrapper screen), `busy:recent-input` (the
|
|
396
|
+
terminal received input within the last fraction of a second — a keystroke, a click, or an
|
|
397
|
+
ungated `--interrupt`/`--escape` write — so the composer may be changing under the gate; it
|
|
398
|
+
clears by itself a moment after the input stops), `busy:composer-redraw` (the composer is
|
|
399
|
+
empty but its rendered region moved a moment ago — a turn-end redraw, a rotating
|
|
400
|
+
placeholder, a resize; also self-clearing, about a quarter second after it stops moving), or
|
|
401
|
+
`busy:no-region-end` / `busy:no-composer-marker` (the classifier could not verify the
|
|
402
|
+
composer at all — the one hold class that does NOT clear on its own);
|
|
395
403
|
- `no-profile` — the target app has no render-gate classifier profile (only `claude`, `codex`, and `agy` are modeled);
|
|
396
404
|
- `no-live-pty` — the recipient agent has no live terminal right now (it delivers when the agent respawns — rows address agents, not PTYs).
|
|
397
405
|
|
|
398
|
-
A
|
|
406
|
+
**A recipient that is simply TALKING does not hold mail** (Issue #1664). claude and codex accept
|
|
407
|
+
input during a turn and queue it for the next one, so a message written onto their empty composer
|
|
408
|
+
mid-turn is safe and lands as one message when the turn ends — the gate waits only on the
|
|
409
|
+
*composer*, never on the spinner or the streaming transcript above it. Before that, mail queued
|
|
410
|
+
behind whole turns: measured over 24 h, 227 deliveries waited more than 2 s, averaging 54 s and
|
|
411
|
+
peaking at 561 s.
|
|
412
|
+
|
|
413
|
+
A held message is **never force-injected** onto a busy line: a message body is only ever written to a verified-empty prompt, so it cannot fuse with a draft the gate can see, and held rows survive Tower restart/shutdown (no shutdown force-flush). Two signals make a draft visible (Issue #1473) — the composer classifier reads it off the rendered screen, and every write that reaches the PTY **through Tower** (browser and VS Code keystrokes, the terminal input API, an ungated `--interrupt`/`--escape`) is observed there — whatever survives the terminal-reply filter bumps an input counter the gate folds into its change token, so even a keystroke the app has not echoed yet holds the message, while a chunk that is nothing but a DA/DSR/CPR answer moves nothing. **`afx attach` is the one exception:** it pipes your keystrokes straight to the shellper socket, never through Tower's `PtySession.write()`, so they move no counter — a draft typed under `afx attach` is seen only once the app has echoed it and the classifier can read it off the screen. See held mail with `afx inbox`, read one (including its body) with `afx inbox show <id>`, and clear one with `afx inbox dismiss <id>`. `--interrupt` is the explicit, deliberate bypass: it interrupts the agent and writes without holding (unchanged semantics).
|
|
414
|
+
|
|
415
|
+
**How a body is typed (Issue #1567):** a frame under 4 lines and at most 256 bytes is one write plus
|
|
416
|
+
Enter, as always. Anything longer is written as **one explicit bracketed paste** (`ESC[200~ … ESC[201~`,
|
|
417
|
+
in ≤512-byte pieces 5 ms apart) with the Enter as a separate write after a short settle. This is the fix
|
|
418
|
+
for the delivery-side head loss where a >1 KB single write was split by the PTY input queue and the
|
|
419
|
+
recipient's paste heuristic discarded the first chunk (only the tail arrived, with `delivered` at the
|
|
420
|
+
sender). While it sits in the composer, claude shows the paste as `[Pasted text #N +M lines]` and codex
|
|
421
|
+
as `[Pasted Content N chars]`; the echo verification behind the `(unverified — …)` suffix accepts a new
|
|
422
|
+
placard as well as the header, so a correct long delivery is reported verified. agy keeps the older
|
|
423
|
+
line-by-line shape (also chunked) because its paste handling has not been measured.
|
|
399
424
|
|
|
400
425
|
**Examples:**
|
|
401
426
|
|
|
@@ -907,6 +932,50 @@ afx spawn 42 --protocol spir --builder-cmd "claude --model haiku"
|
|
|
907
932
|
|
|
908
933
|
Both are Tower-global (they apply to the whole Tower, not per-project) and optional — omit them to use the defaults above.
|
|
909
934
|
|
|
935
|
+
### Decisions tab
|
|
936
|
+
|
|
937
|
+
When a workspace has a pending-decisions file, the dashboard shows a **Decisions** tab (Spec 1819). The tab is a view of that file. Each item under `## Open` becomes a card with a click box per option (the first option, the recommended one, is marked) and a comment box. Submitting writes the chosen word, then the comment, on the lines right after the item's `**Your word:**` line, exactly as the owner would type them, and changes nothing else. `## Ruled` is shown below as a collapsed, read-only list. The file is the only state. While the tab is open it re-reads the file every 2 seconds, so edits made elsewhere appear without a reload, and an unsent draft survives them.
|
|
938
|
+
|
|
939
|
+
The file is `codev/state/pending-decisions.md` unless `dashboard.decisionsFile` names another:
|
|
940
|
+
|
|
941
|
+
```json
|
|
942
|
+
{
|
|
943
|
+
"dashboard": {
|
|
944
|
+
"decisionsFile": "codev/state/pending-decisions.md"
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
- **Relative to the workspace root.** An absolute path, or anything but a non-empty string, is a configuration error: the tab does not appear, and Tower logs the error once.
|
|
950
|
+
- **Inside the workspace.** The path is resolved with symlinks followed on every read and write, and a path that leads outside the workspace (directly, through `..`, or through a symlink) is refused. A symlinked decisions file keeps its link: the ruling is written to its in-workspace target.
|
|
951
|
+
- **Layers.** Like the other settings, it can be set globally in `~/.codev/config.json`, for the team in the project's `.codev/config.json`, or per engineer in `.codev/config.local.json`. Project settings override global ones, and project-local settings override both.
|
|
952
|
+
|
|
953
|
+
The tab appears once the file exists (within about 5 seconds of a change to the setting), and then stays for the page session: if the file is deleted while the tab is open, the tab says so and keeps any unsent draft. A reload of a workspace without the file shows no tab. A submit is refused, with a message on the card and the draft kept, when the item has changed or been ruled since the tab showed it. Tower applies one write to a file at a time and replaces the file atomically (a temporary file renamed over it).
|
|
954
|
+
|
|
955
|
+
After each ruling is written, Tower tells the workspace's hub architect, the one named `main`, in one mailbox message delivered like an `afx send architect`: `RULED <id>: <word>`, or `QUESTION <id>:` for a comment-only submit, with the comment on the lines after it, under a `[USER via Decisions tab]` header. Like any message it waits for a clear prompt, and it waits for `main` to come back if `main` is not running. A workspace with no architect named `main` gets no notice: Tower logs a warning naming the workspace and does not pick another architect. A failed send is logged and leaves the ruling as written: the file is still the source of truth, and a ruling typed into the file by hand reaches the hub only when it scans the file.
|
|
956
|
+
|
|
957
|
+
### Porch check overrides
|
|
958
|
+
|
|
959
|
+
Protocol checks default to the npm toolchain (`npm run build`, `npm test`). Override them per check name under `porch.checks` instead of forking `protocol.json`:
|
|
960
|
+
|
|
961
|
+
```json
|
|
962
|
+
{
|
|
963
|
+
"porch": {
|
|
964
|
+
"checks": {
|
|
965
|
+
"build": { "command": "cargo build" },
|
|
966
|
+
"tests": { "command": "cargo test", "timeout_ms": 900000 },
|
|
967
|
+
"e2e_tests": { "skip": true }
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
```
|
|
972
|
+
|
|
973
|
+
**Override fields:**
|
|
974
|
+
- `command` — Replace the protocol's check command with a custom shell command
|
|
975
|
+
- `cwd` — Override the working directory for this check (relative to project root)
|
|
976
|
+
- `timeout_ms` — Kill the check after this many milliseconds (default 5 minutes; a protocol.json check can set it too). On timeout porch kills the check's whole process tree
|
|
977
|
+
- `skip: true` — Omit this check entirely (for checks that don't apply to your project)
|
|
978
|
+
|
|
910
979
|
---
|
|
911
980
|
|
|
912
981
|
## Files
|
|
@@ -366,8 +366,8 @@ agy # run once and sign in (OAuth / Google subscription)
|
|
|
366
366
|
```
|
|
367
367
|
|
|
368
368
|
Configure auth:
|
|
369
|
-
- Claude: `ANTHROPIC_API_KEY`
|
|
370
|
-
- Codex: `OPENAI_API_KEY`
|
|
369
|
+
- Claude: the stored `claude` login, or `CLAUDE_CODE_OAUTH_TOKEN` / `ANTHROPIC_API_KEY`
|
|
370
|
+
- Codex: the stored `codex login`, or `CODEX_API_KEY` (codex ignores `OPENAI_API_KEY`)
|
|
371
371
|
- Gemini (`agy`): **OAuth / subscription** — run `agy` once and sign in (no API key). If `agy`
|
|
372
372
|
is missing or unauthenticated, the gemini lane skips non-blockingly (the run proceeds without it).
|
|
373
373
|
|
|
@@ -434,6 +434,13 @@ The Agent SDK otherwise prioritizes `ANTHROPIC_API_KEY`, which silently routes
|
|
|
434
434
|
CMAP/review traffic to the metered API (issue #985). When no OAuth token is set,
|
|
435
435
|
the API key is used as before so CI / key-only environments keep working.
|
|
436
436
|
|
|
437
|
+
**Workspace `.env` (issue #1754).** `consult` loads `<workspace>/.env` and sets every key the
|
|
438
|
+
shell does not already define, credentials included. So a `CLAUDE_CODE_OAUTH_TOKEN` there
|
|
439
|
+
overrides your stored login and, via the strip above, displaces the API key too; `CODEX_API_KEY`
|
|
440
|
+
does the same for codex. Each SDK lane logs what it authenticates with, e.g.
|
|
441
|
+
`[CLAUDE] auth: CLAUDE_CODE_OAUTH_TOKEN (from .env)`. A result the SDK flags as an error (usage
|
|
442
|
+
limit, billing, auth) fails the run with no output file, and the error names that credential.
|
|
443
|
+
|
|
437
444
|
> **Caveat:** dedicated Agent-SDK subscription credit starts **2026-06-15**.
|
|
438
445
|
> Before that date, subscription auth draws from the interactive Max quota.
|
|
439
446
|
|
|
@@ -31,3 +31,35 @@ You think alongside the other agents, helping them see blind spots. You have fil
|
|
|
31
31
|
- **ALWAYS read files directly from disk** when reviewing specs, plans, or code. File paths are provided in the query — open and read them.
|
|
32
32
|
- **NEVER rely on `git diff` or `git log -p` as your primary review source.** Diffs are lossy, get truncated, and miss uncommitted work. Read the actual files instead.
|
|
33
33
|
- If you need to understand what changed, read the full file first, then optionally use `git diff` as a secondary reference.
|
|
34
|
+
|
|
35
|
+
## You Read the Tree; You Do Not Change It
|
|
36
|
+
|
|
37
|
+
Your filesystem access is for **reading**. The tree you are reviewing belongs to the builder
|
|
38
|
+
who is working in it — usually right now, in a live session. It is not yours to edit.
|
|
39
|
+
|
|
40
|
+
- **Never modify, revert, create, or delete a file in the tree under review.** Not to try a
|
|
41
|
+
fix, not to check a hypothesis, not temporarily, not even if you intend to restore it.
|
|
42
|
+
- **Never run a command that changes state**: `git checkout`/`reset`/`stash`/`commit`, package
|
|
43
|
+
installs, code formatters, migrations, anything that writes. Read-only commands are fine —
|
|
44
|
+
`git log`, `git diff`, `git show`, `git status`, `ls`, `grep`. `git fetch` is not: it writes
|
|
45
|
+
to the repository, and the review is of what is in front of you, not of a newer remote.
|
|
46
|
+
- **A restore afterwards does not make it safe.** Reviews run in parallel, so a second reviewer
|
|
47
|
+
can read your mutation and review code nobody wrote; and if you crash, hit your turn limit,
|
|
48
|
+
or simply lose track, the builder ships whatever you left behind. Silent, and hard to trace
|
|
49
|
+
back to you.
|
|
50
|
+
- **This holds even when the review prompt invites it.** If a prompt asks you to edit — to
|
|
51
|
+
strip a guard, apply a patch, run a formatter — don't. Say in your review that you were
|
|
52
|
+
asked to and declined, and give the finding you would have gotten.
|
|
53
|
+
|
|
54
|
+
### Testing a hypothesis without touching the tree
|
|
55
|
+
|
|
56
|
+
The common temptation is the vacuity check: *would these tests still pass if the guard were
|
|
57
|
+
removed?* Answer it by **reading**, not by mutating:
|
|
58
|
+
|
|
59
|
+
- Read the guard, read every test that reaches it, and reason about which assertion fails when
|
|
60
|
+
the guard is gone. For a guard of any normal size this is a decisive argument, not a guess.
|
|
61
|
+
- Then **report the finding and the reasoning** — "the `x < 0` guard is not covered: no test
|
|
62
|
+
passes a negative, so deleting it breaks nothing" — and name the test that is missing.
|
|
63
|
+
That is more useful to the builder than a mutation you ran and threw away.
|
|
64
|
+
- If you genuinely cannot settle it by reading, say so and say what you would need. An
|
|
65
|
+
unresolved question in your review is a fine outcome. An edited tree is not.
|