@cluesmith/codev 3.3.1 → 3.3.3

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.
Files changed (248) hide show
  1. package/dashboard-dist/assets/{index-D3XaKpZW.js → index-CUIjS_Vb.js} +41 -41
  2. package/dashboard-dist/assets/index-CUIjS_Vb.js.map +1 -0
  3. package/dashboard-dist/assets/index-DnYLy5C_.css +32 -0
  4. package/dashboard-dist/index.html +2 -2
  5. package/dist/agent-farm/cli.d.ts.map +1 -1
  6. package/dist/agent-farm/cli.js +52 -1
  7. package/dist/agent-farm/cli.js.map +1 -1
  8. package/dist/agent-farm/commands/inbox.d.ts.map +1 -1
  9. package/dist/agent-farm/commands/inbox.js +67 -10
  10. package/dist/agent-farm/commands/inbox.js.map +1 -1
  11. package/dist/agent-farm/commands/interrupt.d.ts +4 -1
  12. package/dist/agent-farm/commands/interrupt.d.ts.map +1 -1
  13. package/dist/agent-farm/commands/interrupt.js +6 -3
  14. package/dist/agent-farm/commands/interrupt.js.map +1 -1
  15. package/dist/agent-farm/commands/reset/constants.d.ts +118 -0
  16. package/dist/agent-farm/commands/reset/constants.d.ts.map +1 -1
  17. package/dist/agent-farm/commands/reset/constants.js +118 -0
  18. package/dist/agent-farm/commands/reset/constants.js.map +1 -1
  19. package/dist/agent-farm/commands/reset/context.d.ts +18 -0
  20. package/dist/agent-farm/commands/reset/context.d.ts.map +1 -1
  21. package/dist/agent-farm/commands/reset/context.js +41 -0
  22. package/dist/agent-farm/commands/reset/context.js.map +1 -1
  23. package/dist/agent-farm/commands/reset/receipt.d.ts.map +1 -1
  24. package/dist/agent-farm/commands/reset/receipt.js +16 -5
  25. package/dist/agent-farm/commands/reset/receipt.js.map +1 -1
  26. package/dist/agent-farm/commands/reset/reorient.d.ts +1 -1
  27. package/dist/agent-farm/commands/reset/reorient.d.ts.map +1 -1
  28. package/dist/agent-farm/commands/reset/reorient.js +8 -1
  29. package/dist/agent-farm/commands/reset/reorient.js.map +1 -1
  30. package/dist/agent-farm/commands/reset/self.d.ts +335 -0
  31. package/dist/agent-farm/commands/reset/self.d.ts.map +1 -0
  32. package/dist/agent-farm/commands/reset/self.js +636 -0
  33. package/dist/agent-farm/commands/reset/self.js.map +1 -0
  34. package/dist/agent-farm/commands/reset.d.ts +4 -1
  35. package/dist/agent-farm/commands/reset.d.ts.map +1 -1
  36. package/dist/agent-farm/commands/reset.js +29 -21
  37. package/dist/agent-farm/commands/reset.js.map +1 -1
  38. package/dist/agent-farm/commands/self-refresh.d.ts +60 -0
  39. package/dist/agent-farm/commands/self-refresh.d.ts.map +1 -0
  40. package/dist/agent-farm/commands/self-refresh.js +506 -0
  41. package/dist/agent-farm/commands/self-refresh.js.map +1 -0
  42. package/dist/agent-farm/commands/send.d.ts +28 -0
  43. package/dist/agent-farm/commands/send.d.ts.map +1 -1
  44. package/dist/agent-farm/commands/send.js +90 -7
  45. package/dist/agent-farm/commands/send.js.map +1 -1
  46. package/dist/agent-farm/commands/spawn.d.ts +7 -0
  47. package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
  48. package/dist/agent-farm/commands/spawn.js +13 -1
  49. package/dist/agent-farm/commands/spawn.js.map +1 -1
  50. package/dist/agent-farm/db/index.d.ts +3 -1
  51. package/dist/agent-farm/db/index.d.ts.map +1 -1
  52. package/dist/agent-farm/db/index.js +8 -443
  53. package/dist/agent-farm/db/index.js.map +1 -1
  54. package/dist/agent-farm/db/mailbox.d.ts +47 -7
  55. package/dist/agent-farm/db/mailbox.d.ts.map +1 -1
  56. package/dist/agent-farm/db/mailbox.js +56 -12
  57. package/dist/agent-farm/db/mailbox.js.map +1 -1
  58. package/dist/agent-farm/db/migrations.d.ts +57 -0
  59. package/dist/agent-farm/db/migrations.d.ts.map +1 -0
  60. package/dist/agent-farm/db/migrations.js +530 -0
  61. package/dist/agent-farm/db/migrations.js.map +1 -0
  62. package/dist/agent-farm/db/schema.d.ts +1 -1
  63. package/dist/agent-farm/db/schema.d.ts.map +1 -1
  64. package/dist/agent-farm/db/schema.js +1 -0
  65. package/dist/agent-farm/db/schema.js.map +1 -1
  66. package/dist/agent-farm/db/types.d.ts +22 -0
  67. package/dist/agent-farm/db/types.d.ts.map +1 -1
  68. package/dist/agent-farm/db/types.js.map +1 -1
  69. package/dist/agent-farm/lib/tower-client.d.ts +12 -0
  70. package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
  71. package/dist/agent-farm/lib/tower-client.js +12 -0
  72. package/dist/agent-farm/lib/tower-client.js.map +1 -1
  73. package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
  74. package/dist/agent-farm/lib/tunnel-client.js +43 -14
  75. package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
  76. package/dist/agent-farm/servers/cron-delivery.d.ts +7 -1
  77. package/dist/agent-farm/servers/cron-delivery.d.ts.map +1 -1
  78. package/dist/agent-farm/servers/cron-delivery.js +2 -1
  79. package/dist/agent-farm/servers/cron-delivery.js.map +1 -1
  80. package/dist/agent-farm/servers/gate-profiles.d.ts +21 -0
  81. package/dist/agent-farm/servers/gate-profiles.d.ts.map +1 -1
  82. package/dist/agent-farm/servers/gate-profiles.js +36 -4
  83. package/dist/agent-farm/servers/gate-profiles.js.map +1 -1
  84. package/dist/agent-farm/servers/mailbox-delivery.d.ts +218 -15
  85. package/dist/agent-farm/servers/mailbox-delivery.d.ts.map +1 -1
  86. package/dist/agent-farm/servers/mailbox-delivery.js +259 -27
  87. package/dist/agent-farm/servers/mailbox-delivery.js.map +1 -1
  88. package/dist/agent-farm/servers/mailbox-wiring.d.ts +66 -11
  89. package/dist/agent-farm/servers/mailbox-wiring.d.ts.map +1 -1
  90. package/dist/agent-farm/servers/mailbox-wiring.js +202 -48
  91. package/dist/agent-farm/servers/mailbox-wiring.js.map +1 -1
  92. package/dist/agent-farm/servers/message-write.d.ts +58 -18
  93. package/dist/agent-farm/servers/message-write.d.ts.map +1 -1
  94. package/dist/agent-farm/servers/message-write.js +73 -28
  95. package/dist/agent-farm/servers/message-write.js.map +1 -1
  96. package/dist/agent-farm/servers/render-gate.d.ts +37 -1
  97. package/dist/agent-farm/servers/render-gate.d.ts.map +1 -1
  98. package/dist/agent-farm/servers/render-gate.js +71 -12
  99. package/dist/agent-farm/servers/render-gate.js.map +1 -1
  100. package/dist/agent-farm/servers/session-submit.d.ts +220 -27
  101. package/dist/agent-farm/servers/session-submit.d.ts.map +1 -1
  102. package/dist/agent-farm/servers/session-submit.js +333 -42
  103. package/dist/agent-farm/servers/session-submit.js.map +1 -1
  104. package/dist/agent-farm/servers/tower-cron.d.ts.map +1 -1
  105. package/dist/agent-farm/servers/tower-cron.js +3 -2
  106. package/dist/agent-farm/servers/tower-cron.js.map +1 -1
  107. package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
  108. package/dist/agent-farm/servers/tower-instances.js +11 -3
  109. package/dist/agent-farm/servers/tower-instances.js.map +1 -1
  110. package/dist/agent-farm/servers/tower-routes.d.ts +32 -0
  111. package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
  112. package/dist/agent-farm/servers/tower-routes.js +245 -36
  113. package/dist/agent-farm/servers/tower-routes.js.map +1 -1
  114. package/dist/agent-farm/servers/tower-server.js +15 -2
  115. package/dist/agent-farm/servers/tower-server.js.map +1 -1
  116. package/dist/agent-farm/servers/tower-terminals.d.ts +21 -0
  117. package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
  118. package/dist/agent-farm/servers/tower-terminals.js +53 -5
  119. package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
  120. package/dist/agent-farm/servers/tower-tunnel.d.ts.map +1 -1
  121. package/dist/agent-farm/servers/tower-tunnel.js +14 -0
  122. package/dist/agent-farm/servers/tower-tunnel.js.map +1 -1
  123. package/dist/agent-farm/servers/tower-utils.d.ts +35 -0
  124. package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
  125. package/dist/agent-farm/servers/tower-utils.js +39 -0
  126. package/dist/agent-farm/servers/tower-utils.js.map +1 -1
  127. package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -1
  128. package/dist/agent-farm/servers/tower-websocket.js +8 -1
  129. package/dist/agent-farm/servers/tower-websocket.js.map +1 -1
  130. package/dist/agent-farm/types.d.ts +36 -1
  131. package/dist/agent-farm/types.d.ts.map +1 -1
  132. package/dist/agent-farm/utils/message-format.d.ts +136 -4
  133. package/dist/agent-farm/utils/message-format.d.ts.map +1 -1
  134. package/dist/agent-farm/utils/message-format.js +212 -22
  135. package/dist/agent-farm/utils/message-format.js.map +1 -1
  136. package/dist/agent-farm/utils/server-utils.d.ts +8 -2
  137. package/dist/agent-farm/utils/server-utils.d.ts.map +1 -1
  138. package/dist/agent-farm/utils/server-utils.js +19 -2
  139. package/dist/agent-farm/utils/server-utils.js.map +1 -1
  140. package/dist/cli.d.ts.map +1 -1
  141. package/dist/cli.js +3 -1
  142. package/dist/cli.js.map +1 -1
  143. package/dist/commands/doctor.js +2 -2
  144. package/dist/commands/generate-image.d.ts +20 -1
  145. package/dist/commands/generate-image.d.ts.map +1 -1
  146. package/dist/commands/generate-image.js +188 -1
  147. package/dist/commands/generate-image.js.map +1 -1
  148. package/dist/commands/porch/context-refresh.d.ts +181 -0
  149. package/dist/commands/porch/context-refresh.d.ts.map +1 -0
  150. package/dist/commands/porch/context-refresh.js +270 -0
  151. package/dist/commands/porch/context-refresh.js.map +1 -0
  152. package/dist/commands/porch/index.d.ts +6 -0
  153. package/dist/commands/porch/index.d.ts.map +1 -1
  154. package/dist/commands/porch/index.js +46 -0
  155. package/dist/commands/porch/index.js.map +1 -1
  156. package/dist/commands/porch/next.d.ts +0 -9
  157. package/dist/commands/porch/next.d.ts.map +1 -1
  158. package/dist/commands/porch/next.js +133 -4
  159. package/dist/commands/porch/next.js.map +1 -1
  160. package/dist/commands/porch/prompts.d.ts.map +1 -1
  161. package/dist/commands/porch/prompts.js +18 -2
  162. package/dist/commands/porch/prompts.js.map +1 -1
  163. package/dist/commands/porch/protocol.d.ts.map +1 -1
  164. package/dist/commands/porch/protocol.js +102 -0
  165. package/dist/commands/porch/protocol.js.map +1 -1
  166. package/dist/commands/porch/types.d.ts +61 -0
  167. package/dist/commands/porch/types.d.ts.map +1 -1
  168. package/dist/lib/forge-contracts.d.ts +66 -5
  169. package/dist/lib/forge-contracts.d.ts.map +1 -1
  170. package/dist/lib/forge-contracts.js.map +1 -1
  171. package/dist/lib/forge.d.ts +1 -1
  172. package/dist/lib/forge.d.ts.map +1 -1
  173. package/dist/lib/forge.js +33 -11
  174. package/dist/lib/forge.js.map +1 -1
  175. package/dist/lib/self-refresh-invocation.d.ts +60 -0
  176. package/dist/lib/self-refresh-invocation.d.ts.map +1 -0
  177. package/dist/lib/self-refresh-invocation.js +64 -0
  178. package/dist/lib/self-refresh-invocation.js.map +1 -0
  179. package/dist/lib/test-env.d.ts +50 -0
  180. package/dist/lib/test-env.d.ts.map +1 -1
  181. package/dist/lib/test-env.js +76 -0
  182. package/dist/lib/test-env.js.map +1 -1
  183. package/dist/terminal/pty-manager.d.ts +10 -1
  184. package/dist/terminal/pty-manager.d.ts.map +1 -1
  185. package/dist/terminal/pty-manager.js +38 -9
  186. package/dist/terminal/pty-manager.js.map +1 -1
  187. package/dist/terminal/pty-session.d.ts +52 -4
  188. package/dist/terminal/pty-session.d.ts.map +1 -1
  189. package/dist/terminal/pty-session.js +157 -18
  190. package/dist/terminal/pty-session.js.map +1 -1
  191. package/dist/terminal/shellper-client.d.ts +73 -0
  192. package/dist/terminal/shellper-client.d.ts.map +1 -1
  193. package/dist/terminal/shellper-client.js +151 -0
  194. package/dist/terminal/shellper-client.js.map +1 -1
  195. package/dist/terminal/shellper-main.js +20 -3
  196. package/dist/terminal/shellper-main.js.map +1 -1
  197. package/dist/terminal/shellper-process.d.ts +2 -0
  198. package/dist/terminal/shellper-process.d.ts.map +1 -1
  199. package/dist/terminal/shellper-process.js +17 -1
  200. package/dist/terminal/shellper-process.js.map +1 -1
  201. package/dist/terminal/shellper-protocol.d.ts +28 -0
  202. package/dist/terminal/shellper-protocol.d.ts.map +1 -1
  203. package/dist/terminal/shellper-protocol.js.map +1 -1
  204. package/package.json +4 -4
  205. package/scripts/forge/gitea/_lib.sh +214 -0
  206. package/scripts/forge/gitea/issue-comment.sh +8 -1
  207. package/scripts/forge/gitea/issue-view.sh +95 -4
  208. package/scripts/forge/gitea/pr-create.sh +155 -0
  209. package/scripts/forge/gitea/pr-exists.sh +32 -4
  210. package/scripts/forge/gitea/pr-list.sh +40 -31
  211. package/scripts/forge/gitea/pr-view.sh +65 -4
  212. package/scripts/forge/gitea/recently-merged.sh +91 -21
  213. package/scripts/forge/gitea/user-identity.sh +30 -1
  214. package/scripts/forge/github/issue-view.sh +5 -2
  215. package/scripts/forge/github/pr-create.sh +47 -0
  216. package/scripts/forge/github/pr-search.sh +3 -1
  217. package/scripts/forge/gitlab/issue-view.sh +24 -4
  218. package/scripts/forge/gitlab/pr-create.sh +53 -0
  219. package/scripts/forge/gitlab/pr-search.sh +3 -1
  220. package/scripts/forge/linear/issue-view.sh +13 -2
  221. package/skeleton/.claude/skills/arch-save/SKILL.md +8 -2
  222. package/skeleton/.claude/skills/builder-refresh/SKILL.md +138 -0
  223. package/skeleton/.claude/skills/generate-image/SKILL.md +22 -1
  224. package/skeleton/.codex/skills/arch-save/SKILL.md +8 -2
  225. package/skeleton/.codex/skills/builder-refresh/SKILL.md +138 -0
  226. package/skeleton/.codex/skills/generate-image/SKILL.md +22 -1
  227. package/skeleton/protocol-schema.json +17 -0
  228. package/skeleton/protocols/air/prompts/pr.md +6 -1
  229. package/skeleton/protocols/air/protocol.json +1 -1
  230. package/skeleton/protocols/aspir/prompts/review.md +6 -1
  231. package/skeleton/protocols/aspir/protocol.json +5 -1
  232. package/skeleton/protocols/bugfix/prompts/pr.md +6 -1
  233. package/skeleton/protocols/bugfix/protocol.json +1 -1
  234. package/skeleton/protocols/bugfix/protocol.md +2 -1
  235. package/skeleton/protocols/experiment/protocol.json +1 -1
  236. package/skeleton/protocols/maintain/prompts/review.md +6 -1
  237. package/skeleton/protocols/maintain/protocol.json +1 -1
  238. package/skeleton/protocols/pir/prompts/review.md +10 -7
  239. package/skeleton/protocols/pir/protocol.json +1 -1
  240. package/skeleton/protocols/protocol-schema.json +17 -0
  241. package/skeleton/protocols/research/protocol.json +1 -1
  242. package/skeleton/protocols/spike/protocol.json +1 -1
  243. package/skeleton/protocols/spir/prompts/review.md +6 -1
  244. package/skeleton/protocols/spir/protocol.json +5 -1
  245. package/skeleton/resources/commands/agent-farm.md +1 -1
  246. package/templates/tower.html +16 -1
  247. package/dashboard-dist/assets/index-BZRTEMtH.css +0 -32
  248. package/dashboard-dist/assets/index-D3XaKpZW.js.map +0 -1
@@ -0,0 +1,53 @@
1
+ #!/bin/sh
2
+ # Forge concept: pr-create (GitLab via glab CLI — merge requests)
3
+ # forge-executable: glab
4
+ #
5
+ # Input: CODEV_PR_TITLE (required)
6
+ # CODEV_PR_BODY (required, may be empty)
7
+ # CODEV_PR_BASE, CODEV_PR_HEAD, CODEV_PR_REPO, CODEV_PR_DRAFT (optional)
8
+ # Output: {"number": <int>, "url": "<web url>"}
9
+ #
10
+ # ⚠️ UNVERIFIED — `glab` is not available in the authoring environment (same
11
+ # constraint as gitea/issue-search.sh, #920). Written against glab's
12
+ # documented `mr create` flags; smoke-test before relying on it. Without this
13
+ # file the gitlab preset would fall through to the GitHub default and shell
14
+ # out to `gh` — the bug this concept exists to close (#1455).
15
+ #
16
+ # `glab mr create --yes` skips the interactive prompts and prints the new MR's
17
+ # URL; the number (GitLab's `iid`) is its last path segment.
18
+ set -e
19
+
20
+ if [ -z "$CODEV_PR_TITLE" ]; then
21
+ echo "pr-create: CODEV_PR_TITLE is required" >&2
22
+ exit 2
23
+ fi
24
+
25
+ # An empty body is allowed; an *absent* one is not. Without this, forgetting the
26
+ # variable opens a PR with no body at exit 0 — the silent failure #1455 is about.
27
+ if [ -z "${CODEV_PR_BODY+x}" ]; then
28
+ echo "pr-create: CODEV_PR_BODY is required (set it to \"\" for an empty body)" >&2
29
+ exit 2
30
+ fi
31
+
32
+ set -- --title "$CODEV_PR_TITLE" --description "$CODEV_PR_BODY" --yes
33
+ if [ -n "$CODEV_PR_BASE" ]; then set -- "$@" --target-branch "$CODEV_PR_BASE"; fi
34
+ if [ -n "$CODEV_PR_HEAD" ]; then set -- "$@" --source-branch "$CODEV_PR_HEAD"; fi
35
+ if [ -n "$CODEV_PR_REPO" ]; then set -- "$@" --repo "$CODEV_PR_REPO"; fi
36
+ if [ "$CODEV_PR_DRAFT" = "1" ]; then set -- "$@" --draft; fi
37
+
38
+ url=$(glab mr create "$@" | grep -E '^https?://' | tail -n 1)
39
+
40
+ if [ -z "$url" ]; then
41
+ echo "pr-create: glab mr create returned no MR URL" >&2
42
+ exit 1
43
+ fi
44
+
45
+ number=${url##*/}
46
+ case "$number" in
47
+ '' | *[!0-9]*)
48
+ echo "pr-create: could not parse an MR number from '$url'" >&2
49
+ exit 1
50
+ ;;
51
+ esac
52
+
53
+ printf '{"number":%s,"url":"%s"}\n' "$number" "$url"
@@ -1,3 +1,5 @@
1
1
  #!/bin/sh
2
2
  # Forge concept: pr-search (GitLab via glab CLI)
3
- exec glab mr list --search "$CODEV_SEARCH_QUERY" --output json
3
+ # --all is required so the search includes merged/closed MRs; without it
4
+ # `glab mr list` defaults to opened only and post-merge lookups return nothing (#759).
5
+ exec glab mr list --all --search "$CODEV_SEARCH_QUERY" --output json
@@ -1,7 +1,13 @@
1
1
  #!/bin/sh
2
2
  # Forge concept: issue-view (Linear via GraphQL API)
3
3
  # Input: CODEV_ISSUE_ID (e.g. "ENG-123")
4
- # Output: JSON {title, body, state, url, comments[]}
4
+ # Output: JSON {title, body, state, url, author, createdAt, assignees, labels, milestone, comments[]}
5
+ #
6
+ # Maps Linear's fields into the forge-neutral IssueView shape. Linear has a
7
+ # single `assignee` (emitted as a one-element `assignees` array) and `project`
8
+ # rather than milestones (mapped into `milestone.title`). These fields are
9
+ # optional by contract, so anything Linear leaves null degrades to an omitted
10
+ # line. Best-effort preset (Spec 589).
5
11
  set -e
6
12
 
7
13
  if [ -z "$LINEAR_API_KEY" ]; then
@@ -18,7 +24,7 @@ curl -sf -X POST https://api.linear.app/graphql \
18
24
  -H "Content-Type: application/json" \
19
25
  -H "Authorization: $LINEAR_API_KEY" \
20
26
  -d "$(jq -n --arg id "$CODEV_ISSUE_ID" '{
21
- query: "query($id: String!) { issueVcsByFilter: issues(filter: { identifier: { eq: $id } }) { nodes { title url description state { name } comments { nodes { body createdAt user { displayName } } } } } }",
27
+ query: "query($id: String!) { issueVcsByFilter: issues(filter: { identifier: { eq: $id } }) { nodes { title url description createdAt state { name } creator { displayName } assignee { displayName } labels { nodes { name } } project { name } comments { nodes { body createdAt user { displayName } } } } } }",
22
28
  variables: { id: $id }
23
29
  }')" \
24
30
  | jq 'if (.data.issueVcsByFilter.nodes | length) == 0 then
@@ -29,6 +35,11 @@ curl -sf -X POST https://api.linear.app/graphql \
29
35
  url: .url,
30
36
  body: (.description // ""),
31
37
  state: .state.name,
38
+ author: (if .creator then { login: .creator.displayName } else null end),
39
+ createdAt: .createdAt,
40
+ assignees: (if .assignee then [{ login: .assignee.displayName }] else [] end),
41
+ labels: [(.labels.nodes // [])[] | { name: .name }],
42
+ milestone: (if .project then { title: .project.name } else null end),
32
43
  comments: [.comments.nodes[] | {
33
44
  body: .body,
34
45
  createdAt: .createdAt,
@@ -107,8 +107,14 @@ guarantee about the clear's completion. If the timing is wrong the re-init arriv
107
107
  wrong moment, which costs one manual message (see below) and nothing else. That is the
108
108
  whole reason this cycle can be built on a delay rather than on machinery.
109
109
 
110
- Delayed sends are **not persisted** — if Tower restarts inside the window, the message is
111
- dropped. That is recoverable; see below.
110
+ Delayed sends **are persisted**. The body is written to the durable mailbox at request time
111
+ with a `not_before` timestamp, so Tower keeps no timer for it and a restart inside the window
112
+ does not lose it — the re-init is delivered once the delay passes. The one thing a restart does
113
+ drop is the Ctrl+C nudge of a delayed `--interrupt`, which this cycle does not use.
114
+
115
+ That removes a failure mode this section used to warn about, but not the need for the recovery
116
+ path below: delivery still waits on an empty prompt, so a re-init can arrive late rather than
117
+ never.
112
118
 
113
119
  **If this send fails, do not end your turn.** Step 4 queued the `/clear`, but it does not
114
120
  take effect until your turn ends — so at this moment you still have your full context and
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: builder-refresh
3
+ description: Refresh a builder's own context at a protocol boundary — save working state, verify it, clear, and re-orient. Use when porch emits a context-refresh task, or the builder is told to "refresh your context" / "run a self-refresh". A builder does not invoke this autonomously mid-task; porch chooses the moment. Counterpart to the architect's /arch-save.
4
+ argument-hint: "(none — porch's refresh task supplies the commands)"
5
+ ---
6
+
7
+ # /builder-refresh — save, clear, and come back knowing where you are
8
+
9
+ You are a builder that has reached a protocol boundary. Your context can be discarded
10
+ here safely, because everything that matters is already on disk: the spec, the plan,
11
+ `status.yaml`, your thread narrative, and git history. A fresh context re-orients from
12
+ those artifacts rather than from memory.
13
+
14
+ **The enforcement is in the command, not in this document.** `afx self-refresh` refuses to
15
+ clear on an unverified save, refuses when the re-entry cannot be scheduled, and refuses
16
+ when your worktree has uncommitted tracked changes. This skill sequences the steps and
17
+ explains the judgement calls; it cannot and does not decide whether the clear is safe.
18
+
19
+ ## When NOT to run this
20
+
21
+ **Porch chooses the moment. You do not.** Run this when porch's refresh task tells you to,
22
+ or when the architect directs it. Do not invoke it mid-task on your own judgement — a
23
+ boundary is a point a fresh context can resume *from*, and a mid-task snapshot resumes into
24
+ confusion.
25
+
26
+ If you are not at a boundary and think you need a refresh anyway, say so to the architect
27
+ rather than doing it: `afx send architect "..."`.
28
+
29
+ ## The procedure
30
+
31
+ ### 1. Use the commands porch gave you
32
+
33
+ Porch's refresh task contains the exact two commands for this boundary, including the
34
+ `--boundary` flag. **Run those, verbatim.**
35
+
36
+ Do not retype them from memory and do not omit the flag. `--boundary` binds the challenge
37
+ to the boundary it was issued at, so a challenge left behind by an aborted refresh cannot
38
+ be used to clear you at a *later* boundary, against a save describing work that has since
39
+ moved on. That guard has been silently disabled twice by an instruction that dropped the
40
+ flag, which is why this document deliberately does not restate the commands.
41
+
42
+ If you arrived here without a porch task — an architect-directed refresh, say — there is no
43
+ boundary to bind, and the flagless form is correct. Run `afx self-refresh --help` for the
44
+ exact spelling rather than guessing it.
45
+
46
+ ### 2. Write your working state
47
+
48
+ The first command prints a save request naming a file and a marker line. Write that file.
49
+
50
+ **The marker must be the FIRST LINE**, reproduced exactly. A save whose nonce appears
51
+ further down is refused — that check exists because echoing the request back into the file
52
+ otherwise passed every gate, and echoing instructions is something agents do by accident.
53
+
54
+ **Write for a cold reader** — a competent agent that wakes up with your worktree, your
55
+ branch, and no memory of this conversation. Most of your state is already on disk, so do
56
+ not restate the spec or the plan. Carry only what the artifacts do not contain:
57
+
58
+ - **receipts** — what is done and *verified*, with paths and commit hashes, distinguishing
59
+ "written" from "verified";
60
+ - **deviations** from the plan, and why;
61
+ - **flaky or skipped tests**, and what you did about them;
62
+ - **deferred work**, and the reason;
63
+ - **standing orders** from the architect you are still bound by, including anything you
64
+ were told NOT to do;
65
+ - **the next concrete action**.
66
+
67
+ Pointers, not prose. The save has a minimum size, and it is not a word count to pad — a
68
+ file below it is indistinguishable from a stub. If you genuinely have less than that to
69
+ say, you are probably omitting receipts or standing orders.
70
+
71
+ ### 3. Run the execute command, then stop
72
+
73
+ The second command verifies your save, writes a re-orientation to disk, schedules your
74
+ re-entry, and clears you — in that order, and only if every step succeeds.
75
+
76
+ **Then end your turn.** Do not start new work. The clear takes effect when the turn ends.
77
+
78
+ ## If it refuses
79
+
80
+ Most refusals happen **before** anything destructive, and those leave your context
81
+ untouched. One does not. Read which you got.
82
+
83
+ ### Pre-clear refusals — your context is intact
84
+
85
+ | Refusal | What it means |
86
+ |---|---|
87
+ | state file missing / too small / wrong nonce | Your save did not satisfy the gate — check the marker is on line 1 |
88
+ | worktree has uncommitted tracked changes | Commit first; a refreshed context re-orients from git, so uncommitted work is invisible to it |
89
+ | Tower is not running, or did not schedule the re-entry | Clearing would strand you, so it refused |
90
+ | challenge missing / already consumed / for a different boundary | Run the begin step again |
91
+ | invalid parameters | A flag is out of range — nothing was read or written |
92
+ | challenge could not be marked consumed | Nothing was cleared, but a re-entry **is** already queued and will arrive; ignore it. Retrying queues a second one |
93
+
94
+ For any of these: **report it and carry on.**
95
+
96
+ ```bash
97
+ afx send architect "Context refresh refused at <boundary>: <the reason it printed>"
98
+ ```
99
+
100
+ Then run `porch next` for your normal tasks. **The refresh never blocks your work** — the
101
+ boundary is recorded as consumed either way, so a failed refresh costs you some context and
102
+ nothing else.
103
+
104
+ ### `clear-failed` — you cannot assume anything
105
+
106
+ If the command reports that the clear was attempted but **may still have landed**, do not
107
+ treat that as a pre-clear refusal. Sending `/clear` can succeed on the wire and still report
108
+ an error, so from inside this turn it is genuinely unknown whether your context survives.
109
+
110
+ - A re-entry message **is** already queued and will arrive shortly. If your context was
111
+ cleared, that message is your re-orientation. If it was not, the message is harmless and
112
+ can be ignored.
113
+ - Do not start new work in this state.
114
+ - Tell the architect explicitly that the outcome is ambiguous:
115
+
116
+ ```bash
117
+ afx send architect "Self-refresh clear-failed at <boundary> — clear may or may not have landed; re-entry is queued"
118
+ ```
119
+
120
+ ## After the clear
121
+
122
+ A re-entry message arrives shortly, identifying itself as an automatic context refresh. It
123
+ carries your identity, protocol, project, worktree and branch, and points at
124
+ `.builder-reorient.md` — the full spawn-quality frame, on disk.
125
+
126
+ It will tell you to run `porch next`. Do that; porch's state is untouched by the clear and
127
+ its next task emission *is* your re-orientation.
128
+
129
+ **If the re-entry never arrives**, nothing is lost. `.builder-reorient.md` is on disk and
130
+ the architect can send you back with one message. Say so if you notice.
131
+
132
+ ## What this does not do
133
+
134
+ - It does not write `status.yaml`. Only porch does, and the boundary is already recorded
135
+ there before you are asked to refresh.
136
+ - It does not decide *whether* to refresh. Porch decided that.
137
+ - It does not retry. A boundary is refreshed at most once, so a refusal means this boundary
138
+ simply does not get a refresh.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: generate-image
3
- description: AI image generation via Gemini. 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 GEMINI_API_KEY or GOOGLE_API_KEY.
3
+ description: AI image generation via Gemini, or Atlas Cloud with `-p atlas`. 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 GEMINI_API_KEY or GOOGLE_API_KEY, or ATLASCLOUD_API_KEY when using `-p atlas`.
4
4
  ---
5
5
 
6
6
  # generate-image - AI Image Generation
@@ -22,6 +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: gemini (default) or atlas
25
26
  ```
26
27
 
27
28
  ## Aspect ratios
@@ -43,3 +44,23 @@ codev generate-image prompt.txt -o result.png # Prompt from .txt file
43
44
  - Prompt can be a `.txt` file path (auto-detected by extension)
44
45
  - Reference images must exist on disk
45
46
  - Requires `GEMINI_API_KEY` or `GOOGLE_API_KEY` environment variable
47
+
48
+ ## Alternative provider: Atlas Cloud
49
+
50
+ `-p atlas` generates through Atlas Cloud, which serves the same Nano Banana Pro
51
+ model over a submit-then-poll REST API. Useful when a Google AI Studio key is
52
+ not available. Requires `ATLASCLOUD_API_KEY`; the default provider is unchanged.
53
+
54
+ ```bash
55
+ codev generate-image "A sunset over mountains" -p atlas -a 16:9
56
+ ```
57
+
58
+ Measured differences on that path:
59
+
60
+ - `-a/--aspect` works (`1:1` returns 1024x1024, `16:9` returns 1376x768).
61
+ - `-r/--resolution` has no equivalent field; a note is printed and the model's
62
+ default resolution comes back.
63
+ - `--ref` is not supported (text-to-image only) and exits with an error rather
64
+ than silently ignoring the images.
65
+ - The model returns JPEG, so the output file is named after its actual bytes
66
+ instead of writing JPEG into the default `output.png`.
@@ -107,8 +107,14 @@ guarantee about the clear's completion. If the timing is wrong the re-init arriv
107
107
  wrong moment, which costs one manual message (see below) and nothing else. That is the
108
108
  whole reason this cycle can be built on a delay rather than on machinery.
109
109
 
110
- Delayed sends are **not persisted** — if Tower restarts inside the window, the message is
111
- dropped. That is recoverable; see below.
110
+ Delayed sends **are persisted**. The body is written to the durable mailbox at request time
111
+ with a `not_before` timestamp, so Tower keeps no timer for it and a restart inside the window
112
+ does not lose it — the re-init is delivered once the delay passes. The one thing a restart does
113
+ drop is the Ctrl+C nudge of a delayed `--interrupt`, which this cycle does not use.
114
+
115
+ That removes a failure mode this section used to warn about, but not the need for the recovery
116
+ path below: delivery still waits on an empty prompt, so a re-init can arrive late rather than
117
+ never.
112
118
 
113
119
  **If this send fails, do not end your turn.** Step 4 queued the `/clear`, but it does not
114
120
  take effect until your turn ends — so at this moment you still have your full context and
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: builder-refresh
3
+ description: Refresh a builder's own context at a protocol boundary — save working state, verify it, clear, and re-orient. Use when porch emits a context-refresh task, or the builder is told to "refresh your context" / "run a self-refresh". A builder does not invoke this autonomously mid-task; porch chooses the moment. Counterpart to the architect's /arch-save.
4
+ argument-hint: "(none — porch's refresh task supplies the commands)"
5
+ ---
6
+
7
+ # /builder-refresh — save, clear, and come back knowing where you are
8
+
9
+ You are a builder that has reached a protocol boundary. Your context can be discarded
10
+ here safely, because everything that matters is already on disk: the spec, the plan,
11
+ `status.yaml`, your thread narrative, and git history. A fresh context re-orients from
12
+ those artifacts rather than from memory.
13
+
14
+ **The enforcement is in the command, not in this document.** `afx self-refresh` refuses to
15
+ clear on an unverified save, refuses when the re-entry cannot be scheduled, and refuses
16
+ when your worktree has uncommitted tracked changes. This skill sequences the steps and
17
+ explains the judgement calls; it cannot and does not decide whether the clear is safe.
18
+
19
+ ## When NOT to run this
20
+
21
+ **Porch chooses the moment. You do not.** Run this when porch's refresh task tells you to,
22
+ or when the architect directs it. Do not invoke it mid-task on your own judgement — a
23
+ boundary is a point a fresh context can resume *from*, and a mid-task snapshot resumes into
24
+ confusion.
25
+
26
+ If you are not at a boundary and think you need a refresh anyway, say so to the architect
27
+ rather than doing it: `afx send architect "..."`.
28
+
29
+ ## The procedure
30
+
31
+ ### 1. Use the commands porch gave you
32
+
33
+ Porch's refresh task contains the exact two commands for this boundary, including the
34
+ `--boundary` flag. **Run those, verbatim.**
35
+
36
+ Do not retype them from memory and do not omit the flag. `--boundary` binds the challenge
37
+ to the boundary it was issued at, so a challenge left behind by an aborted refresh cannot
38
+ be used to clear you at a *later* boundary, against a save describing work that has since
39
+ moved on. That guard has been silently disabled twice by an instruction that dropped the
40
+ flag, which is why this document deliberately does not restate the commands.
41
+
42
+ If you arrived here without a porch task — an architect-directed refresh, say — there is no
43
+ boundary to bind, and the flagless form is correct. Run `afx self-refresh --help` for the
44
+ exact spelling rather than guessing it.
45
+
46
+ ### 2. Write your working state
47
+
48
+ The first command prints a save request naming a file and a marker line. Write that file.
49
+
50
+ **The marker must be the FIRST LINE**, reproduced exactly. A save whose nonce appears
51
+ further down is refused — that check exists because echoing the request back into the file
52
+ otherwise passed every gate, and echoing instructions is something agents do by accident.
53
+
54
+ **Write for a cold reader** — a competent agent that wakes up with your worktree, your
55
+ branch, and no memory of this conversation. Most of your state is already on disk, so do
56
+ not restate the spec or the plan. Carry only what the artifacts do not contain:
57
+
58
+ - **receipts** — what is done and *verified*, with paths and commit hashes, distinguishing
59
+ "written" from "verified";
60
+ - **deviations** from the plan, and why;
61
+ - **flaky or skipped tests**, and what you did about them;
62
+ - **deferred work**, and the reason;
63
+ - **standing orders** from the architect you are still bound by, including anything you
64
+ were told NOT to do;
65
+ - **the next concrete action**.
66
+
67
+ Pointers, not prose. The save has a minimum size, and it is not a word count to pad — a
68
+ file below it is indistinguishable from a stub. If you genuinely have less than that to
69
+ say, you are probably omitting receipts or standing orders.
70
+
71
+ ### 3. Run the execute command, then stop
72
+
73
+ The second command verifies your save, writes a re-orientation to disk, schedules your
74
+ re-entry, and clears you — in that order, and only if every step succeeds.
75
+
76
+ **Then end your turn.** Do not start new work. The clear takes effect when the turn ends.
77
+
78
+ ## If it refuses
79
+
80
+ Most refusals happen **before** anything destructive, and those leave your context
81
+ untouched. One does not. Read which you got.
82
+
83
+ ### Pre-clear refusals — your context is intact
84
+
85
+ | Refusal | What it means |
86
+ |---|---|
87
+ | state file missing / too small / wrong nonce | Your save did not satisfy the gate — check the marker is on line 1 |
88
+ | worktree has uncommitted tracked changes | Commit first; a refreshed context re-orients from git, so uncommitted work is invisible to it |
89
+ | Tower is not running, or did not schedule the re-entry | Clearing would strand you, so it refused |
90
+ | challenge missing / already consumed / for a different boundary | Run the begin step again |
91
+ | invalid parameters | A flag is out of range — nothing was read or written |
92
+ | challenge could not be marked consumed | Nothing was cleared, but a re-entry **is** already queued and will arrive; ignore it. Retrying queues a second one |
93
+
94
+ For any of these: **report it and carry on.**
95
+
96
+ ```bash
97
+ afx send architect "Context refresh refused at <boundary>: <the reason it printed>"
98
+ ```
99
+
100
+ Then run `porch next` for your normal tasks. **The refresh never blocks your work** — the
101
+ boundary is recorded as consumed either way, so a failed refresh costs you some context and
102
+ nothing else.
103
+
104
+ ### `clear-failed` — you cannot assume anything
105
+
106
+ If the command reports that the clear was attempted but **may still have landed**, do not
107
+ treat that as a pre-clear refusal. Sending `/clear` can succeed on the wire and still report
108
+ an error, so from inside this turn it is genuinely unknown whether your context survives.
109
+
110
+ - A re-entry message **is** already queued and will arrive shortly. If your context was
111
+ cleared, that message is your re-orientation. If it was not, the message is harmless and
112
+ can be ignored.
113
+ - Do not start new work in this state.
114
+ - Tell the architect explicitly that the outcome is ambiguous:
115
+
116
+ ```bash
117
+ afx send architect "Self-refresh clear-failed at <boundary> — clear may or may not have landed; re-entry is queued"
118
+ ```
119
+
120
+ ## After the clear
121
+
122
+ A re-entry message arrives shortly, identifying itself as an automatic context refresh. It
123
+ carries your identity, protocol, project, worktree and branch, and points at
124
+ `.builder-reorient.md` — the full spawn-quality frame, on disk.
125
+
126
+ It will tell you to run `porch next`. Do that; porch's state is untouched by the clear and
127
+ its next task emission *is* your re-orientation.
128
+
129
+ **If the re-entry never arrives**, nothing is lost. `.builder-reorient.md` is on disk and
130
+ the architect can send you back with one message. Say so if you notice.
131
+
132
+ ## What this does not do
133
+
134
+ - It does not write `status.yaml`. Only porch does, and the boundary is already recorded
135
+ there before you are asked to refresh.
136
+ - It does not decide *whether* to refresh. Porch decided that.
137
+ - It does not retry. A boundary is refreshed at most once, so a refusal means this boundary
138
+ simply does not get a refresh.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: generate-image
3
- description: AI image generation via Gemini. 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 GEMINI_API_KEY or GOOGLE_API_KEY.
3
+ description: AI image generation via Gemini, or Atlas Cloud with `-p atlas`. 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 GEMINI_API_KEY or GOOGLE_API_KEY, or ATLASCLOUD_API_KEY when using `-p atlas`.
4
4
  ---
5
5
 
6
6
  # generate-image - AI Image Generation
@@ -22,6 +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: gemini (default) or atlas
25
26
  ```
26
27
 
27
28
  ## Aspect ratios
@@ -43,3 +44,23 @@ codev generate-image prompt.txt -o result.png # Prompt from .txt file
43
44
  - Prompt can be a `.txt` file path (auto-detected by extension)
44
45
  - Reference images must exist on disk
45
46
  - Requires `GEMINI_API_KEY` or `GOOGLE_API_KEY` environment variable
47
+
48
+ ## Alternative provider: Atlas Cloud
49
+
50
+ `-p atlas` generates through Atlas Cloud, which serves the same Nano Banana Pro
51
+ model over a submit-then-poll REST API. Useful when a Google AI Studio key is
52
+ not available. Requires `ATLASCLOUD_API_KEY`; the default provider is unchanged.
53
+
54
+ ```bash
55
+ codev generate-image "A sunset over mountains" -p atlas -a 16:9
56
+ ```
57
+
58
+ Measured differences on that path:
59
+
60
+ - `-a/--aspect` works (`1:1` returns 1024x1024, `16:9` returns 1376x768).
61
+ - `-r/--resolution` has no equivalent field; a note is printed and the model's
62
+ default resolution comes back.
63
+ - `--ref` is not supported (text-to-image only) and exits with an error rather
64
+ than silently ignoring the images.
65
+ - The model returns JPEG, so the output file is named after its actual bytes
66
+ instead of writing JPEG into the default `output.png`.
@@ -39,6 +39,23 @@
39
39
  "description": "Signals that can be emitted during protocol execution",
40
40
  "additionalProperties": { "$ref": "#/$defs/signal" }
41
41
  },
42
+ "context_refresh": {
43
+ "type": "object",
44
+ "description": "Boundaries at which builders automatically refresh their context (Spec 1470). Absent means no refreshes.",
45
+ "additionalProperties": false,
46
+ "properties": {
47
+ "on_enter": {
48
+ "type": "array",
49
+ "description": "Protocol phase ids to refresh on entry to. Each must name a phase this protocol declares.",
50
+ "uniqueItems": true,
51
+ "items": { "type": "string" }
52
+ },
53
+ "on_plan_phase_advance": {
54
+ "type": "boolean",
55
+ "description": "Refresh when advancing from one plan phase to the next. Requires a 'per_plan_phase' phase. Excludes the first plan phase, which coincides with entering the phase itself."
56
+ }
57
+ }
58
+ },
42
59
  "phase_completion": {
43
60
  "type": "object",
44
61
  "description": "Checks run when a plan phase completes",
@@ -18,7 +18,8 @@ Open the PR with the review embedded in its body, optionally run CMAP, and notif
18
18
  The body must carry `Closes #<N>` for the driving issue — one per issue if several — so GitHub auto-closes it on merge. **Exception:** a partial fix uses `Refs #<N>` or `Part of #<N>` instead. Substitute the real number for `<N>`; leave no `{{...}}` tag or `<N>` placeholder in the committed body.
19
19
 
20
20
  ```bash
21
- gh pr create --title "[Air #<N>] feat: <brief description>" --body "$(cat <<'EOF'
21
+ export CODEV_PR_TITLE="[Air #<N>] feat: <brief description>"
22
+ export CODEV_PR_BODY="$(cat <<'EOF'
22
23
  ## Summary
23
24
 
24
25
  <1-2 sentence description of the feature>
@@ -44,8 +45,12 @@ Closes #<N> <!-- Substitute <N>; use "Refs #<N>" for a partial fix -->
44
45
  <anything the reviewer should focus on, or "Standard implementation — no special concerns">
45
46
  EOF
46
47
  )"
48
+
49
+ {{pr_create_command}}
47
50
  ```
48
51
 
52
+ The command above is your forge's `pr-create` concept, substituted by porch (`gh pr create` by default). It takes `CODEV_PR_TITLE` / `CODEV_PR_BODY` — optionally `CODEV_PR_BASE`, `CODEV_PR_HEAD`, `CODEV_PR_REPO` — from the environment, which is why they are exported rather than prefixed onto the command line: an inline override that spells `--title "$CODEV_PR_TITLE"` needs them set in the calling shell too. It prints `{"number": <int>, "url": "<url>"}`.
53
+
49
54
  ## Optional CMAP review
50
55
 
51
56
  CMAP is your judgement call for AIR. Skip it for simple changes (config, small UI); run it for features touching core logic or several modules:
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "../../protocol-schema.json",
2
+ "$schema": "../protocol-schema.json",
3
3
  "name": "air",
4
4
  "version": "1.0.0",
5
5
  "description": "AIR: Autonomous Implement & Review — lightweight protocol for small features from GitHub Issues",
@@ -44,7 +44,8 @@ The review's `## Architecture Updates` and `## Lessons Learned Updates` sections
44
44
  The PR body must carry `Closes #<N>` (feature) or `Fixes #<N>` (bug) for the driving issue — one keyword per issue if several — so GitHub auto-closes on merge. **Exception:** a PR that only partially addresses its issue uses `Refs #<N>` or `Part of #<N>` instead, leaving the issue open for the follow-up.
45
45
 
46
46
  ```bash
47
- gh pr create --title "[Spec {{project_id}}] {{title}}" --body "$(cat <<'EOF'
47
+ export CODEV_PR_TITLE="[Spec {{project_id}}] {{title}}"
48
+ export CODEV_PR_BODY="$(cat <<'EOF'
48
49
  ## Summary
49
50
  [what was implemented]
50
51
 
@@ -63,8 +64,12 @@ codev/specs/{{artifact_name}}.md
63
64
  codev/reviews/{{artifact_name}}.md
64
65
  EOF
65
66
  )"
67
+
68
+ {{pr_create_command}}
66
69
  ```
67
70
 
71
+ The command above is your forge's `pr-create` concept, substituted by porch (`gh pr create` by default). It takes `CODEV_PR_TITLE` / `CODEV_PR_BODY` — optionally `CODEV_PR_BASE`, `CODEV_PR_HEAD`, `CODEV_PR_REPO` — from the environment, which is why they are exported rather than prefixed onto the command line: an inline override that spells `--title "$CODEV_PR_TITLE"` needs them set in the calling shell too. It prints `{"number": <int>, "url": "<url>"}`.
72
+
68
73
  ## Signals
69
74
 
70
75
  - Review document complete:
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "../../protocol-schema.json",
2
+ "$schema": "../protocol-schema.json",
3
3
  "name": "aspir",
4
4
  "version": "1.0.0",
5
5
  "description": "ASPIR: Autonomous SPIR — Specify → Plan → Implement → Review without human approval gates",
@@ -8,6 +8,10 @@
8
8
  "required": false,
9
9
  "default_for": ["--project", "-p"]
10
10
  },
11
+ "context_refresh": {
12
+ "on_enter": ["plan", "implement", "review"],
13
+ "on_plan_phase_advance": true
14
+ },
11
15
  "phases": [
12
16
  {
13
17
  "id": "specify",
@@ -16,7 +16,8 @@ Open the PR, run CMAP review on it, address feedback, and hand off to the archit
16
16
  The PR body must carry `Fixes #<N>` for the driving issue — one per issue if several — so GitHub auto-closes it on merge. **Exception:** a PR that only partially addresses the issue uses `Refs #<N>` or `Part of #<N>` instead, leaving it open for the follow-up. Substitute the real number for `<N>`; leave no `{{...}}` tag or `<N>` placeholder in the committed body.
17
17
 
18
18
  ```bash
19
- gh pr create --title "Fix #<N>: <brief description>" --body "$(cat <<'EOF'
19
+ export CODEV_PR_TITLE="Fix #<N>: <brief description>"
20
+ export CODEV_PR_BODY="$(cat <<'EOF'
20
21
  ## Summary
21
22
 
22
23
  <1-2 sentence description of the bug and fix>
@@ -38,8 +39,12 @@ Fixes #<N> <!-- Substitute <N>; use "Refs #<N>" for a partial fix -->
38
39
  - [ ] All tests pass
39
40
  EOF
40
41
  )"
42
+
43
+ {{pr_create_command}}
41
44
  ```
42
45
 
46
+ The command above is your forge's `pr-create` concept, substituted by porch (`gh pr create` by default). It takes `CODEV_PR_TITLE` / `CODEV_PR_BODY` — optionally `CODEV_PR_BASE`, `CODEV_PR_HEAD`, `CODEV_PR_REPO` — from the environment, which is why they are exported rather than prefixed onto the command line: an inline override that spells `--title "$CODEV_PR_TITLE"` needs them set in the calling shell too. It prints `{"number": <int>, "url": "<url>"}`.
47
+
43
48
  ## Run CMAP review
44
49
 
45
50
  BUGFIX runs its own 3-way consultation on the PR (porch does not do it for you). Dispatch all three in the background:
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "../../protocol-schema.json",
2
+ "$schema": "../protocol-schema.json",
3
3
  "name": "bugfix",
4
4
  "version": "1.2.0",
5
5
  "description": "Lightweight protocol for minor bugfixes using GitHub Issues",
@@ -27,7 +27,8 @@ refactor surrounding code, fix unrelated bugs (file separate issues), or add fea
27
27
  [Bugfix #42] Test: regression for unencoded username
28
28
  ```
29
29
 
30
- **PR** — open with `gh pr create`, body carrying Summary, Root Cause, Fix and Test Plan plus
30
+ **PR** — open with the `pr-create` forge concept command the PR-phase prompt hands you (`gh
31
+ pr create` on GitHub), body carrying Summary, Root Cause, Fix and Test Plan plus
31
32
  `Fixes #<N>` so the issue closes on merge. Run one CMAP pass (Gemini, Codex, Claude), record
32
33
  each verdict, and address or rebut every `REQUEST_CHANGES`. Notify the architect with the
33
34
  verdicts, then `porch done <id>` and wait.
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "../../protocol-schema.json",
2
+ "$schema": "../protocol-schema.json",
3
3
  "name": "experiment",
4
4
  "version": "1.0.0",
5
5
  "description": "Disciplined experimentation with hypothesis testing",