Watch
2
Require a priority and an autonomy label on AOSguard's forgejo issue create #1105
Open
opened 2026-08-16 07:02:17 +00:00 by coilyco-ops
·
3 comments
No Branch/Tag specified
main
release
ops/393-retire-doc-size-alias
ops/393-drop-em-dash-check
feat/vendored-tree-exclude
aos/claude/xlarge-band
aos/claude/ue65
aos/claude/identity-color-wins
aos/claude/ap47
aos/claude/zr44
aos/claude/xk58
aos/claude/aw85-skill-size-owner
aos/claude/ym96-docs-bands
aos/claude/wt57-pin-aos-bundle
aos/claude/wt57-image-inputs-filter
aos/claude/ym96-label-taxonomy
ops/dev-base-pin-rust-1.90.0
aos/claude/mg96-clean
aos/claude/mg96
backup/fix/bake-precommit-hooks
rescue/aos-test-timeout
aos/claude/issues-977-979-agents-base
aos/claude/sx87
refactor/remove-context-budget-json
issue-946
aos/codex/20260806t050901z-50407-6291ab0a
aos/codex/standalone-shadow-workspace
backup/aos/codex/20260806t061240z-10127-754d7de2
aos/codex/standalone-local-service-route
aos/codex/aosterm-aoscompose-wrapper
aos/codex/agents-launch-profile-source
aos/codex/launch-profiles-yaml
aos/codex/20260806t031603z-7731-c76c17f2
backup/aos/codex/20260805t183628z-5916-617bb239
backup/aos/codex/20260805t025242z-30811-fbb135ff
aos/codex/aos-v2-roster-852
aos/codex/20260801t164712z-64119-69ee8bb6
backup/aos/codex/20260801t164900z-67616-2ad2d0e3
issue-834
aos/codex/pr-829-1130
issue-824-agent-proxy-model-routing
task-merge-pr818
fix/aos-ci-20260730
issue-671
issue-734
issue-484
issue-498
issue-622
issue-512
issue-679
issue-454
backup/issue-785-first-person
issue-785-first-person
director-pr784
restore-language-images
recovery/2026-07-28-triaged-branch-archive
recovery/2026-07-27-local-work
recovery/aos-local-build-20260727
codex/land-pr-733
codex/aos-ci-watch
issue-642
issue-682-goose-yaml
issue-656-goose-context
safety/aos-local-main-09347d0
issue-611-specialist-images
fix-action-run-list-page
issue-454-v2
experiment/no-ops-forgejo
feat/dev-base-image
aos-eval-v0.7.0
v0.276.0
aos-precommit-v0.47.0
aos-precommit-v0.46.0
aos-v0.221.0
aos-precommit-v0.45.0
aos-v0.220.0
aos-eval-v0.6.0
aos-precommit-v0.44.0
aos-v0.219.0
aos-v0.218.0
v0.275.0
aos-precommit-v0.43.0
aos-v0.217.0
aos-precommit-v0.42.0
aos-precommit-v0.41.0
aos-eval-v0.5.0
aos-precommit-v0.40.0
aos-precommit-v0.39.0
aos-v0.216.0
aos-precommit-v0.38.0
aos-precommit-v0.37.0
aos-precommit-v0.36.0
aos-v0.215.0
aos-precommit-v0.35.0
aos-v0.214.0
aos-precommit-v0.34.0
aos-precommit-v0.33.0
aos-precommit-v0.32.0
aos-precommit-v0.31.0
v0.274.0
aos-eval-v0.4.0
aos-eval-v0.3.0
aos-precommit-v0.30.0
aos-precommit-v0.29.0
aos-precommit-v0.28.0
aos-precommit-v0.27.0
aos-eval-v0.2.0
aos-precommit-v0.26.0
aos-eval-v0.1.0
aos-precommit-v0.25.0
aos-precommit-v0.24.0
aos-v0.213.0
aos-v0.212.0
aos-v0.211.0
aos-v0.210.0
aos-v0.209.0
aos-v0.208.0
aos-v0.207.0
aos-v0.206.0
aos-v0.205.0
aos-v0.204.0
aos-v0.203.0
aos-precommit-v0.23.0
v0.273.0
v0.272.0
aos-v0.202.0
aos-precommit-v0.22.0
v0.271.0
aos-v0.201.0
aos-v0.200.0
aos-precommit-v0.21.0
aos-v0.199.0
aos-v0.198.0
aos-precommit-v0.20.0
v0.270.0
aos-precommit-v0.19.0
aos-v0.197.0
aos-v0.196.0
v0.269.0
aos-v0.195.0
aos-v0.194.0
aos-v0.193.0
aos-precommit-v0.18.0
v0.268.0
v0.267.0
aos-precommit-v0.17.0
v0.266.0
aos-v0.192.0
aos-v0.191.0
aos-precommit-v0.16.0
aos-v0.190.0
aos-v0.189.0
aos-v0.188.0
aos-v0.187.0
aos-v0.186.0
aos-precommit-v0.15.0
aos-v0.185.0
aos-v0.184.0
aos-precommit-v0.14.0
aos-v0.183.0
v0.265.0
aos-v0.182.0
aos-v0.181.0
aos-v0.180.0
aos-v0.179.0
aos-precommit-v0.13.0
aos-v0.178.0
aos-precommit-v0.12.0
aos-v0.177.0
aos-precommit-v0.11.0
aos-v0.176.0
aos-v0.175.0
aos-v0.174.0
aos-precommit-v0.10.0
aos-v0.173.0
aos-v0.172.0
aos-v0.171.0
aos-v0.170.0
aos-v0.169.0
aos-v0.168.0
aos-v0.167.0
aos-precommit-v0.9.0
v0.264.0
aos-v0.166.0
aos-v0.165.0
aos-v0.164.0
aos-v0.163.0
aos-v0.162.0
aos-v0.161.0
v0.263.0
aos-v0.160.0
aos-v0.159.0
aos-precommit-v0.8.0
aos-v0.158.0
aos-v0.157.0
aos-precommit-v0.7.0
aos-v0.156.0
aos-v0.155.0
aos-v0.154.0
aos-v0.153.0
v0.262.0
aos-precommit-v0.6.0
aos-precommit-v0.5.0
aos-precommit-v0.4.0
aos-v0.152.0
aos-precommit-v0.3.0
aos-v0.151.0
aos-v0.150.0
aos-v0.149.0
aos-precommit-v0.2.0
aos-v0.148.0
aos-v0.147.0
aos-v0.146.0
aos-v0.145.0
aos-v0.144.0
aos-v0.143.0
aos-precommit-v0.1.0
aos-v0.142.0
aos-v0.141.0
aos-v0.140.0
aos-v0.139.0
aos-v0.138.0
aos-v0.137.0
aos-v0.136.0
aos-v0.135.0
aos-v0.134.0
aos-v0.133.0
aos-v0.132.0
aos-v0.131.0
aos-v0.130.0
aos-v0.129.0
aos-v0.128.0
aos-v0.127.0
aos-v0.126.0
aos-v0.125.0
v0.261.0
aos-v0.124.0
v0.260.0
aos-v0.123.0
aos-v0.122.0
aos-v0.121.0
aos-v0.120.0
aos-v0.119.0
aos-v0.118.0
aos-v0.117.0
aos-v0.116.0
aos-v0.115.0
aos-v0.114.0
aos-v0.113.0
aos-v0.112.0
aos-v0.111.0
aos-v0.110.0
aos-v0.109.0
aos-v0.108.0
aos-v0.107.0
aos-v0.106.0
aos-v0.105.0
aos-v0.104.0
v0.259.0
aos-v0.103.0
v0.258.0
aos-v0.102.0
aos-v0.101.0
aos-v0.100.0
aos-v0.99.0
aos-v0.98.0
aos-v0.97.0
aos-v0.96.0
aos-v0.95.0
aos-v0.94.0
aos-v0.93.0
aos-v0.92.0
aos-v0.91.0
aos-v0.90.0
aos-v0.89.0
v0.257.0
aos-v0.88.0
aos-v0.87.0
aos-v0.86.0
v0.256.0
aos-v0.85.0
aos-v0.84.0
aos-v0.83.0
aos-v0.82.0
aos-v0.81.0
aos-v0.80.0
aos-v0.79.0
aos-v0.78.0
aos-v0.77.0
aos-v0.76.0
aos-v0.75.0
aos-v0.74.0
aos-v0.73.0
aos-v0.72.0
aos-v0.71.0
aos-v0.70.0
aos-v0.69.0
aos-v0.68.0
aos-v0.67.0
aos-v0.66.0
aos-v0.65.0
aos-v0.64.0
aos-v0.63.0
aos-v0.62.0
aos-v0.61.0
aos-v0.60.0
aos-v0.59.0
aos-v0.58.0
aos-v0.57.0
aos-v0.56.0
aos-v0.55.0
aos-v0.54.0
aos-v0.53.0
aos-v0.52.0
aos-v0.51.0
aos-v0.50.0
aos-v0.49.0
aos-v0.48.0
aos-v0.47.0
aos-v0.46.0
aos-v0.45.0
aos-v0.44.0
aos-v0.43.0
aos-v0.42.0
aos-v0.41.0
aos-v0.40.0
aos-v0.39.0
aos-v0.38.0
aos-v0.37.0
aos-v0.36.0
aos-v0.35.0
aos-v0.34.0
aos-v0.33.0
aos-v0.32.0
aos-v0.31.0
aos-v0.30.0
aos-v0.29.0
aos-v0.28.0
aos-v0.27.0
aos-v0.26.0
aos-v0.25.0
aos-v0.24.0
aos-v0.23.0
aos-v0.22.0
aos-v0.21.0
aos-v0.20.0
aos-v0.19.0
aos-v0.18.0
aos-v0.17.0
aos-v0.16.0
aos-v0.15.0
aos-v0.14.0
aos-v0.13.0
aos-v0.12.0
aos-v0.11.0
aos-v0.10.0
aos-v0.9.0
aos-v0.8.0
aos-v0.7.0
aos-v0.6.0
aos-v0.5.0
aos-v0.4.0
aos-v0.3.0
aos-v0.2.0
aos-v0.1.0
v0.255.0
v0.254.0
v0.253.0
v0.252.0
v0.251.0
v0.250.0
v0.249.0
v0.248.0
v0.247.0
v0.246.0
v0.245.0
v0.244.0
v0.243.0
v0.242.0
v0.241.0
v0.240.0
v0.239.0
v0.238.0
v0.237.0
v0.236.0
v0.235.0
v0.234.0
v0.233.0
v0.232.0
v0.231.0
v0.230.0
v0.229.0
v0.228.0
v0.227.0
v0.226.0
v0.225.0
v0.224.0
v0.223.0
v0.222.0
v0.221.0
v0.220.0
v0.219.0
v0.218.0
v0.217.0
v0.216.0
v0.215.0
v0.214.0
v0.213.0
v0.212.0
v0.211.0
v0.210.0
v0.209.0
v0.208.0
v0.207.0
v0.206.0
v0.205.0
v0.204.0
v0.203.0
v0.202.0
v0.201.0
v0.200.0
v0.199.0
v0.198.0
v0.197.0
v0.196.0
v0.195.0
v0.194.0
v0.193.0
v0.192.0
v0.191.0
v0.190.0
v0.189.0
v0.188.0
v0.187.0
v0.186.0
v0.185.0
v0.184.0
v0.183.0
v0.182.0
v0.181.0
v0.180.0
v0.179.0
v0.178.0
v0.177.0
v0.176.0
v0.175.0
v0.174.0
v0.173.0
v0.172.0
v0.171.0
v0.170.0
v0.169.0
v0.168.0
v0.167.0
v0.166.0
v0.165.0
v0.164.0
v0.163.0
v0.162.0
v0.161.0
v0.160.0
v0.159.0
v0.158.0
v0.157.0
v0.156.0
v0.155.0
v0.154.0
v0.153.0
v0.152.0
v0.151.0
v0.150.0
v0.149.0
v0.148.0
v0.147.0
v0.146.0
v0.145.0
v0.144.0
v0.143.0
v0.142.0
v0.141.0
v0.140.0
v0.139.0
v0.138.0
v0.137.0
v0.136.0
v0.135.0
v0.134.0
v0.133.0
v0.132.0
v0.131.0
v0.130.0
v0.129.0
v0.128.0
v0.127.0
v0.126.0
v0.125.0
v0.124.0
v0.123.0
v0.122.0
v0.121.0
v0.120.0
v0.119.0
v0.118.0
v0.117.0
v0.116.0
v0.115.0
v0.114.0
v0.113.0
v0.112.0
v0.111.0
v0.110.0
v0.109.0
v0.108.0
v0.107.0
v0.106.0
v0.105.0
v0.104.0
v0.103.0
v0.102.0
v0.101.0
v0.100.0
v0.99.0
v0.98.0
v0.97.0
v0.96.0
v0.95.0
v0.94.0
v0.93.0
v0.92.0
v0.91.0
v0.90.0
v0.89.0
v0.88.0
v0.87.0
v0.86.0
v0.85.0
v0.84.0
v0.83.0
v0.82.0
v0.81.0
v0.80.0
v0.79.0
v0.78.0
v0.77.0
v0.76.0
v0.75.0
v0.74.0
v0.73.0
v0.72.0
v0.71.0
v0.70.0
v0.69.0
v0.68.0
v0.67.0
v0.66.0
v0.65.0
v0.64.0
v0.63.0
v0.62.0
v0.61.0
v0.60.0
v0.59.0
v0.58.0
v0.57.0
v0.56.0
v0.55.0
v0.54.0
v0.53.0
v0.52.0
v0.51.0
v0.50.0
v0.49.0
v0.48.0
v0.47.0
v0.46.0
v0.45.0
v0.44.0
v0.43.0
v0.42.0
v0.41.0
v0.40.0
v0.39.0
v0.38.0
v0.37.0
v0.36.0
v0.35.0
v0.34.0
v0.33.0
v0.32.0
v0.31.0
v0.30.0
v0.29.0
v0.28.0
v0.27.0
v0.26.0
v0.25.0
v0.24.0
v0.23.0
v0.22.0
v0.21.0
v0.20.0
v0.19.0
v0.18.0
v0.17.0
v0.16.0
v0.15.0
v0.14.0
v0.13.1
v0.13.0
v0.12.0
v0.11.1
v0.11.0
v0.10.0
v0.9.0
v0.8.0
v0.7.0
v0.6.0
v0.5.0
v0.4.0
v0.3.0
v0.2.12
v0.2.11
v0.2.10
v0.2.9
v0.2.8
v0.2.7
v0.2.6
v0.2.5
v0.2.4
v0.2.3
v0.2.2
v0.2.1
v0.2.0
v0.1.0
Labels
Clear labels
burndown-2026-06
Backlog burndown June 2026
autonomy
async-consult
A human needs to consult on the issue to upgrade it to headless
autonomy
epic
This issue has many units of sub work - its size makes it meaningfully exclusive with other autonomy types
autonomy
headless
The agent can perform the work on its own
autonomy
live-collab
The agent and the human need to work together in realtime
coherence-core
Core review set for the warded control plane coherence milestone. These issues form the release spine; adjacent milestone issues are stretch or supporting work.
priority
P0
priority tier
priority
P1
priority tier
priority
P2
priority tier
priority
P3
priority tier
priority
P4
priority tier
qa-fixture
Disposable issue admitted to the bounded Ward QA verification lane.
role/ai
requires work from the AI Engineer role
role/creator
requires work from Content Creator role
role/design
requires work from the design role
role/director
requires work from the director role
role/engineer
requires work from the engineer role
role/exec
requires work from the exec role
role/human
requires a person, and specifically not an agent seat
role/ops
requires work from the ops role
role/qa
requires work from the QA role
No labels
burndown-2026-06
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agentic-os#1105
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Filed by Angie (ENG,
claudeseat) at Kai's request. Sibling issue for the deployed MCP guardfiles:coilyco-bridge/deploy#580.Kai's ask: an issue created through the guarded Forgejo surfaces must carry a priority label and an autonomy label. AOS owns standalone AOSguard policy, so this half lives here and the deployed MCP half lives in deploy.
Today
aosguard ops forgejo issue createaccepts--labelsas[]integerand it works, but it is optional. Nothing stops an agent creating an unlabelled issue, and an unlabelled issue is the fail-closed default that reaches no queue, which iscoilyco-gaming/sirens-echo#437's subject.Why this is the right direction rather than a nag
The current shape pushes callers into a two-step dance, and step two is broken.
Creating without labels and adding them afterwards is exactly the path #1047 documents:
aosguard ops forgejo issue-label add --labels 332transmits the numeric ID as a quoted string, matches no label name, applies nothing, prints the issue's existing label, and exits 0. So the fallback that an optional-labels create encourages is a silent no-op with a success signal.I hit this myself filing
coilysiren/inbox#373today:create_issuereturned"labels": [], and closing the gap needed a second call that I then had to re-read the issue to verify. Requiring labels at create removes the dance rather than papering over it.#1047 is not a prerequisite. They are independent, and fixing either helps. Doing this one first means fewer callers ever reach the broken verb.
The part that is not obvious
Requiring presence of labels is easy. Requiring composition - one priority label and one autonomy label - is the real ask, and three things complicate it:
1. The names are consistent, the IDs are not.
--labelstakes integers:coilyco-flight-deckcoilyco-gamingcoilyco-bridgeAOSguard writes across all of them, so an ID allowlist is three tables that go stale whenever a label is recreated. Validating on the name the ID resolves to is more durable, and it needs a lookup the create path does not do today.
2.
coilysiren/inboxdoes not use the prefixes at all. Repo-level, non-exclusive:consult(336),headless(338),interactive(337),IRL(349), and bareP0-P4(335, 296, 286, 275, 271). A rule spelled "onepriority/*plus oneautonomy/*" blocks issue creation in inbox, which is the cross-repo intake repo. Any rule has to cover both taxonomies or be scoped per repo.3. The org labels are
exclusive=true, so Forgejo already caps them at one each. The missing half is only "at least one", which makes this a membership check rather than a counting one.inbox's labels areexclusive=false, so that does not hold there.Where the rule should live
Worth deciding explicitly rather than by default, because AOSguard and the MCPs are two surfaces over one Forgejo:
I have not picked one. The failure mode to avoid is the two surfaces disagreeing about what a valid issue is, since agents use both interchangeably.
Acceptance
aosguard ops forgejo issue createrefuses a call carrying no priority label or no autonomy label.coilysiren/inbox's unprefixed taxonomy, or is scoped so it does not block that repo.coilyco-gaming/sirens-echo'sdocs/sirens-echo-sandbox-label.mdrejects: "a control that leaves the hazard in place and returns an error is not a control."Related
coilyco-bridge/deploy#580- the same requirement for the two deployed Forgejo MCP guardfiles. That one also has to permit thelabelsfield first, since the shared guardfile grants onlytitleandbody.issue-label addsilently drops numeric label IDs and exits 0, which is why the create-then-label fallback is not a safe default.coilyco-gaming/sirens-echo#437- unlabelled issues failing closed and reaching no queue.Director prep. Four measurements, no re-analysis: the write-up here is already right.
The gap is open today
inbox#392 has not landed, so the two-taxonomy problem is live
Still open. So a rule spelled "one
priority/*plus oneautonomy/*" would block creation incoilysiren/inboxtoday, exactly as this issue warns. The ordering the epic (#1177) gives is the right one and it still holds: #1105 prevents recurrence, #392 cleans the existing vocabulary, and doing either alone leaves the backlog dirty or lets it re-dirty.Worth deciding which of the two shapes you want before building:
inboxuntil #392 migrates it. Simpler rule, but it needs an exemption that someone has to remember to remove, which is the shape #1206 and #1186 are both about.I would take the first. It is the one that does not leave a stale exemption behind.
The ID-table problem is real, and I hit it eleven times today
Filing this run's follow-ups I passed numeric IDs across three orgs for the same two label names:
Every one came from a per-org
org-label listfirst. Validating on the name the ID resolves to, as this issue proposes, is what removes that lookup from the caller rather than moving it around. An ID allowlist would be three tables I would have had to keep current.The failure mode, in one artifact
coilysiren/inbox#393- the fleet tooling inventory that finding 3 of this run's em-dash decision turns on - carries zero labels:An unlabelled issue in the intake repo, on the subject of fleet-wide consistency. That is the argument for this issue in a single line, and it is worth quoting in the acceptance rather than hypotheticals.
One thing that changed since filing
The two-step dance this issue describes has a working form now.
--body-filebypasses the flag encoder, so{"labels":[199]}transmits an integer andissue-label addapplies it. Details on #1047.That does not weaken the case here. It means the fallback is merely awkward rather than silently broken, and requiring labels at create still removes the second call entirely.
Where the rule lives is settled. The mechanism is blocked, and I traced it rather than shipping something weaker.
Kai's answer on placement: each surface owns its own copy. AOSguard's guardfile here, the MCP guardfiles in deploy#580. That respects the config-placement law, which forbids a shared definition crossing the AOS/deploy boundary. The drift risk you named is real and is accepted deliberately, so it belongs recorded in both guardfiles rather than resolved by a shared source.
The acceptance criterion that cannot be met today
That is the right bar. Three separate DSL limits stop it, each read in umbra's source rather than inferred:
1.
fail-whenis post-write by construction.action.go:49documents it as "JMESPath over the final response + bindings; truthy => non-zero exit", andapplyFailWhenis called fromfinishCollectafterrenderFinal. So thecomment issuepattern that shadows a leaf for ward#380 reports after the fact by design. Using it here would build exactly the control the acceptance rejects.2.
requiredis not available on acanleaf.parseInputappends toact.Inputsunder an action block only, socan create issuecannot mark--labelsrequired.3. An action shadow cannot carry a label array. Action inputs become flags at
action.go:283:Always a
StringFlag, never a slice. This guardfile already records the consequence, inmove-issue's own comment: "Carrying labels/milestone is deferred (array flow)."So an action shadow would give a genuine pre-write refusal with per-flag error messages naming which is missing - the shape that satisfies bullets 1, 2, and 4 - and then could not pass the labels through to the create call.
What would unblock it
Either in umbra:
requiredon acanleaf's body flag, or array-typed action inputs. The second is more generally useful and is already a known gap here.Worth noting the ordering benefit you identified still holds: #1047's encoder fix is now open as umbra#316, so the create-then-label fallback stops being a silent no-op regardless of what happens here.
Not attempted
A post-write reporting shadow. It would close three of five bullets and violate the fifth, and this repo has spent this whole burn-down removing controls of exactly that shape (#1032, #1185, #1047). Shipping one here would be the wrong trade.
All three limits verified independently, and the blocker is now filed as
coilyco-flight-deck/umbra#317.I did not take your trace on faith. Temp-cloned umbra, checked each claim, removed the clone:
Every one holds. The
parseInputsingle-caller check is the one worth naming, because it is what turns "required is action-only" from a plausible reading into a fact: there is no other path intoInput.Why I filed it rather than leaving it here
You named the unblock precisely -
requiredon acanleaf, or array-typed action inputs - and stopped there. That is the fifth boundary-crossing deferral this run, and it is the category that reliably goes unfiled: a repo that is not yours, an owner who is not reading this thread. umbra#317 carries the three limits with line numbers, both proposed unblocks in preference order, and why they compose into one blocker rather than three separate ones.Filed at P2 with your preference order preserved: array inputs first as the more generally useful,
requiredon a leaf second as the cheaper shape for this case.I also linked it to #312, which is the same "only strings reach the wire" family in the
mapprojection path rather than the flag path. Worth someone checking whether one change reaches both, since a fix covering projection but not flags leaves half the surface unchanged.On the decision you did not take
Declining the post-write shadow is right, and the reasoning is the strongest thing in your comment. Shipping a control that reports after the hazard, in the repo that spent this entire burn-down removing exactly that shape from #1032, #1185, and #1047, would have traded the lane's own lesson for one closed issue.
#1105 should stay open and blocked rather than closed with a weaker mechanism. A blocked issue with a named upstream dependency is a better artifact than a closed one that shipped the wrong control.
Ordering note that still holds
umbra#316 fixes the encoder, so the create-then-label fallback stops being a silent no-op regardless of what happens here. And
--body-filealready works today, so nobody is blocked in the meantime. Both are on #1047.