Watch
2
advisor ref mode runs native (host one-shot); containerize it like engineer + freeform modes #411
Closed
opened 2026-07-01 08:13:59 +00:00 by coilysiren
·
5 comments
No Branch/Tag specified
main
release
docs/readme-agents-surface
fix/pr-repair-verb-lookup
aos/claude/aw85-docs-bands
aos/claude/aw85-declare-band
aos/claude/bk79-autonomy-label-scope
fix/gofmt-runner
chore/umbra-rename
aos/claude/mg96-fm
claude/agents-temp-clone-note
aos/claude/qa57
remove-format-exec-gate-refusal
fix/ward-1649-ci-fixture
fix/detached-ci-exec
issue-1626-generic-agent-broker
issue-1177
issue-1160
issue-1501
ward-salvage/ward-12486bc7
ward-salvage/ward-babfa2ba
ward-salvage/ward-a832df03
ward-salvage/ward-85c795b2
ward-salvage/ward-b87f8859
issue-1484
ward-salvage/ward-86b72dcf
ward-salvage/ward-b7b26d1d
recovery/2026-07-28-triaged-branch-archive
recovery/2026-07-27-local-work
issue-1584
issue-1571
issue-1524
ward-salvage/ward-3800c2d1
ward-salvage/ward-70175da3
ward-salvage/ward-bcbfef78
issue-1298
issue-737-signoz-deferred
ward-salvage/ward-c6aa5da9
ward-salvage/ward-94dd7346
ward-salvage/ward-58aa3fe3
ward-salvage/ward-ff6c509f
ward-salvage/ward-e80f0460
ward-salvage/ward-3e2e4760
ward-salvage/ward-649addd7
ward-salvage/ward-890e4d29
ward-salvage/ward-645b750b
ward-salvage/ward-bf851a72
ward-salvage/ward-98c8652f
ward-salvage/ward-bb10b620
ward-salvage/ward-1ee9be1c
ward-salvage/ward-d18595f6
ward-salvage/ward-5f914692
ward-salvage/ward-6ca05cbd
ward-salvage/ward-14f676cf
ward-salvage/ward-de811c20
ward-salvage/ward-eba3e824
ward-salvage/ward-16eb4ad0
ward-salvage/ward-c58e9c43
ward-salvage/ward-7487270b
v0.890.0
v0.889.0
v0.888.0
v0.887.0
v0.886.0
v0.885.0
v0.884.0
v0.883.0
v0.882.0
v0.881.0
v0.880.0
v0.879.0
v0.878.0
v0.877.0
v0.876.0
v0.875.0
v0.874.0
v0.873.0
v0.872.0
v0.871.0
v0.870.0
v0.869.0
v0.868.0
v0.867.0
v0.866.0
v0.865.0
v0.864.0
v0.863.0
v0.862.0
v0.861.0
v0.860.0
v0.859.0
v0.858.0
v0.857.0
v0.856.0
v0.855.0
v0.854.0
v0.853.0
v0.852.0
v0.851.0
v0.850.0
v0.849.0
v0.848.0
v0.847.0
v0.846.0
v0.845.0
v0.844.0
v0.843.0
v0.842.0
v0.841.0
v0.840.0
v0.839.0
v0.838.0
v0.837.0
v0.836.0
v0.835.0
v0.834.0
v0.833.0
v0.832.0
v0.830.0
v0.831.0
v0.829.0
v0.828.0
v0.827.0
v0.826.0
v0.825.0
v0.824.0
v0.823.0
v0.822.0
v0.821.0
v0.820.0
v0.819.0
v0.818.0
v0.817.0
v0.816.0
v0.815.0
v0.814.0
v0.813.0
v0.812.0
v0.811.0
v0.810.0
v0.809.0
v0.808.0
v0.807.0
v0.806.0
v0.805.0
v0.804.0
v0.803.0
v0.802.0
v0.801.0
v0.800.0
v0.799.0
v0.798.0
v0.797.0
v0.796.0
v0.795.0
v0.794.0
v0.793.0
v0.792.0
v0.791.0
v0.790.0
v0.789.0
v0.788.0
v0.787.0
v0.786.0
v0.785.0
v0.784.0
v0.783.0
v0.782.0
v0.781.0
v0.780.0
v0.779.0
v0.778.0
v0.777.0
v0.775.0-tmp
v0.776.0
v0.775.0
v0.774.0
v0.773.0
v0.772.0
v0.771.0
v0.770.0
v0.769.0
v0.768.0
v0.767.0
v0.766.0
v0.765.0
v0.764.0
v0.763.0
v0.762.0
v0.761.0
v0.760.0
v0.759.0
v0.758.0
v0.757.0
v0.756.0
v0.755.0
v0.754.0
v0.753.0
v0.752.0
v0.751.0
v0.750.0
v0.749.0
v0.748.0
v0.747.0
v0.746.0
v0.745.0
v0.744.0
v0.743.0
v0.742.0
v0.741.0
v0.740.0
v0.739.0
v0.738.0
v0.737.0
v0.736.0
v0.735.0
v0.734.0
v0.733.0
v0.732.0
v0.731.0
v0.730.0
v0.729.0
v0.728.0
v0.727.0
v0.726.0
v0.725.0
v0.724.0
v0.723.0
v0.722.0
v0.721.0
v0.720.0
v0.719.0
v0.718.0
v0.717.0
v0.716.0
v0.715.0
v0.714.0
v0.713.0
v0.712.0
v0.711.0
v0.710.0
v0.709.0
v0.708.0
v0.707.0
v0.706.0
v0.705.0
v0.704.0
v0.703.0
v0.702.0
v0.701.0
v0.700.0
v0.699.0
v0.698.0
v0.697.0
v0.696.0
v0.695.0
v0.694.0
v0.693.0
v0.692.0
v0.691.0
v0.690.0
v0.689.0
v0.688.0
v0.687.0
v0.686.0
v0.685.0
v0.684.0
v0.683.0
v0.682.0
v0.681.0
v0.680.0
v0.679.0
v0.678.0
v0.677.0
v0.676.0
v0.675.0
v0.674.0
v0.673.0
v0.672.0
v0.671.0
v0.670.0
v0.669.0
v0.668.0
v0.667.0
v0.666.0
v0.665.0
v0.664.0
v0.663.0
v0.662.0
v0.661.0
v0.660.0
v0.659.0
v0.658.0
v0.657.0
v0.656.0
v0.655.0
v0.654.0
v0.653.0
v0.652.0
v0.651.0
v0.650.0
v0.649.0
v0.648.0
v0.647.0
v0.646.0
v0.645.0
v0.644.0
v0.643.0
v0.642.0
v0.641.0
v0.640.0
v0.639.0
v0.638.0
v0.637.0
v0.636.0
v0.635.0
v0.634.0
v0.633.0
v0.632.0
v0.631.0
v0.630.0
v0.629.0
v0.628.0
v0.627.0
v0.626.0
v0.625.0
v0.624.0
v0.623.0
v0.622.0
v0.621.0
v0.620.0
v0.619.0
v0.618.0
v0.617.0
v0.616.0
v0.615.0
v0.614.0
v0.613.0
v0.612.0
v0.611.0
v0.610.0
v0.609.0
v0.608.0
v0.607.0
v0.606.0
v0.605.0
v0.604.0
v0.603.0
v0.602.0
v0.601.0
v0.600.0
v0.599.0
v0.598.0
v0.597.0
v0.596.0
v0.595.0
v0.594.0
v0.593.0
v0.592.0
v0.591.0
v0.590.0
v0.589.0
v0.588.0
v0.587.0
v0.586.0
v0.585.0
v0.584.0
v0.583.0
v0.582.0
v0.581.0
v0.580.0
v0.579.0
v0.578.0
v0.577.0
v0.576.0
v0.575.0
v0.574.0
v0.573.0
v0.572.0
v0.571.0
v0.570.0
v0.569.0
v0.568.0
v0.567.0
v0.566.0
v0.565.0
v0.564.0
v0.563.0
v0.562.0
v0.561.0
v0.560.0
v0.559.0
v0.558.0
v0.557.0
v0.556.0
v0.555.0
v0.554.0
v0.553.0
v0.552.0
v0.551.0
v0.550.0
v0.549.0
v0.548.0
v0.547.0
v0.546.0
v0.545.0
v0.544.0
v0.543.0
v0.542.0
v0.541.0
v0.540.0
v0.539.0
v0.538.0
v0.537.0
v0.536.0
v0.535.0
v0.534.0
v0.533.0
v0.532.0
v0.531.0
v0.530.0
v0.529.0
v0.528.0
v0.527.0
v0.526.0
v0.525.0
v0.524.0
v0.523.0
v0.522.0
v0.521.0
v0.520.0
v0.519.0
v0.518.0
v0.517.0
v0.516.0
v0.515.0
v0.514.0
v0.513.0
v0.512.0
v0.511.0
v0.510.0
v0.509.0
v0.508.0
v0.507.0
v0.506.0
v0.505.0
v0.504.0
v0.503.0
v0.502.0
v0.501.0
v0.500.0
v0.499.0
v0.498.0
v0.497.0
v0.496.0
v0.495.0
v0.494.0
v0.493.0
v0.492.0
v0.491.0
v0.490.0
v0.489.0
v0.488.0
v0.487.0
v0.486.0
v0.485.0
v0.484.0
v0.483.0
v0.482.0
v0.481.0
v0.480.0
v0.479.0
v0.478.0
v0.477.0
v0.476.0
v0.475.0
v0.474.0
v0.473.0
v0.472.0
v0.471.0
v0.470.0
v0.469.0
v0.468.0
v0.467.0
v0.466.0
v0.465.0
v0.464.0
v0.463.0
v0.462.0
v0.461.0
v0.460.0
v0.459.0
v0.458.0
v0.457.0
v0.456.0
v0.455.0
v0.454.0
v0.453.0
v0.452.0
v0.451.0
v0.450.0
v0.449.0
v0.448.0
v0.447.0
v0.446.0
v0.445.0
v0.444.0
v0.443.0
v0.442.0
v0.441.0
v0.440.0
v0.439.0
v0.438.0
v0.437.0
v0.436.0
v0.435.0
v0.434.0
v0.433.0
v0.432.0
v0.431.0
v0.430.0
v0.429.0
v0.428.0
v0.427.0
v0.426.0
v0.425.0
v0.424.0
v0.423.0
v0.422.0
v0.421.0
v0.420.0
v0.419.0
v0.418.0
v0.417.0
v0.416.0
v0.415.0
v0.414.0
v0.413.0
v0.412.0
v0.411.0
v0.410.0
v0.409.0
v0.408.0
v0.407.0
v0.406.0
v0.405.0
v0.404.0
v0.403.0
v0.402.0
v0.401.0
v0.400.0
v0.399.0
v0.398.0
v0.397.0
v0.396.0
v0.395.0
v0.394.0
v0.393.0
v0.392.0
v0.391.0
v0.390.0
v0.389.0
v0.388.0
v0.387.0
v0.386.0
v0.385.0
v0.384.0
v0.383.0
v0.382.0
v0.381.0
v0.380.0
v0.379.0
v0.378.0
v0.377.0
v0.376.0
v0.375.0
v0.374.0
v0.373.0
v0.372.0
v0.371.0
v0.370.0
v0.369.0
v0.368.0
v0.367.0
v0.366.0
v0.365.0
v0.364.0
v0.363.0
v0.362.0
v0.361.0
v0.360.0
v0.359.0
v0.358.0
v0.357.0
v0.356.0
v0.355.0
v0.354.0
v0.353.0
v0.352.0
v0.351.0
v0.350.0
v0.349.0
v0.348.0
v0.347.0
v0.346.0
v0.345.0
v0.344.0
v0.343.0
v0.342.0
v0.341.0
v0.340.0
v0.339.0
v0.338.0
v0.337.0
v0.336.0
v0.335.0
v0.334.0
v0.333.0
v0.332.0
v0.331.0
v0.330.0
v0.329.0
v0.328.0
v0.327.0
v0.326.0
v0.325.0
v0.324.0
v0.323.0
v0.322.0
v0.321.0
v0.320.0
v0.319.0
v0.318.0
v0.317.0
v0.316.0
v0.315.0
v0.314.0
v0.313.0
v0.312.0
v0.311.0
v0.310.0
v0.309.0
v0.308.0
v0.307.0
v0.306.0
v0.305.0
v0.304.0
v0.303.0
v0.302.0
v0.301.0
v0.300.0
v0.299.0
v0.298.0
v0.297.0
v0.296.0
v0.295.0
v0.294.0
v0.293.0
v0.292.0
v0.291.0
v0.290.0
v0.289.0
v0.288.0
v0.287.0
v0.286.0
v0.285.0
v0.284.0
v0.283.0
v0.282.0
v0.281.0
v0.280.0
v0.279.0
v0.278.0
v0.277.0
v0.276.0
v0.275.0
v0.274.0
v0.273.0
v0.272.0
v0.271.0
v0.270.0
v0.269.0
v0.268.0
v0.267.0
v0.266.0
v0.265.0
v0.264.0
v0.263.0
v0.262.0
v0.261.0
v0.260.0
v0.259.0
v0.258.0
v0.257.0
v0.256.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.0
v0.12.0
v0.11.0
v0.10.0
v0.9.0
v0.8.0
v0.7.0
v0.6.0
v0.5.8
v0.5.7
v0.5.6
v0.5.5
v0.5.4
v0.5.3
v0.5.2
v0.5.1
v0.5.0
v0.4.0
v0.3.0
v0.2.2
v0.2.1
v0.2.0
v0.1.3
v0.1.2
v0.1.1
v0.1.0
v0.0.18
v0.0.17
v0.0.16
v0.0.15
v0.0.14
v0.0.13
v0.0.12
v0.0.11
v0.0.10
v0.0.9
v0.0.8
v0.0.7
v0.0.6
v0.0.5
v0.0.4
v0.0.3
v0.0.2
v0.0.1
Labels
Clear labels
burndown-2026-06
Backlog burndown June 2026
pressure-test
Cold-read release pressure-test findings and coordination
sunday-sprint
Burn-down by Sunday 2026-06-07
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/advocate
requires work from the Developer Advocate seat
role/director
requires work from the Portfolio Director seat
role/exec
requires work from the exec role
role/frontend
requires work from the Frontend Engineer seat
role/gamedev
requires work from the Game Developer seat
role/human
requires a person, and specifically not an agent seat
role/platform
requires work from the Platform Engineer seat
role/qa
requires work from the QA role
role/science
requires work from the Applied Scientist seat
role/sysadmin
requires work from the Systems Administrator seat
state
ambient
ambient and ephemeral work, held as a maintained document rather than a queue
No labels
burndown-2026-06
pressure-test
sunday-sprint
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/advocate
role/director
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/science
role/sysadmin
state
ambient
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
2 participants
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/ward#411
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?
Problem
runAgentAdvisor(cmd/ward/agent_advisor.go:69-79) splits by argument type:owner/repo#N) ->runAgentReply= a host one-shot research pass, native, no container (agent_reply.go:14, ward#179).runAgentAsk= a fresh attached ephemeral container (agent_advisor.go:82-120).Engineer always runs in a container. So ref-mode advisor is the lone native outlier among the agent modes. Kai wants it containerized like the others.
Why change it
/substrate+ clones; a container gives it the same clean, reproducible working tree every other mode gets.commentIssue --body-fileskew). A container lifecycle can land its artifact more robustly.Decision owner: Kai (deferred)
The approach is a design call Kai will make. Open questions to settle then:
runAgentAsk) bring-up, or a shared extraction?Dispatched sub-component (now)
A grounding research pass (dispatched against this issue) to arm the decision above: enumerate the current ref-vs-freeform mechanism, the reuse surface (engineer vs
runAgentAskcontainer bring-up), the comment-from-container question, and 2-3 concrete design options with tradeoffs. The build waits on Kai's pick.Mode
consult.
🔎 ward agent advisor
ward agent advisor --driver clauderan a one-shot standard research pass on this question:Now I have a complete, precise picture. Writing the research comment.
1. How each mode runs today
Both modes hang off
runAgentAdvisor(cmd/ward/agent_advisor.go:71-80), which splits purely on whether the first arg parses as an issue ref:Ref mode (
owner/repo#Nor issue URL) →runAgentReply(cmd/ward/agent_reply.go:77-123). This is the native host one-shot:validateReplyInputs(agent_reply.go:127-161) parses the ref, joins the tail as the prompt, resolves--thoroughnessto areplyThoroughnessrung (quick/standard/deep, with3m/8m/15mtimeouts,agent_reply.go:30-51), trust-gates the owner against the primary-org set, and asserts the mode has a host one-shot slot. Onlyclaudeandgoosequalify -hostPreflightArgv(container_compute.go:195-206) returnsclaude -p <prompt>/goose run -t <prompt>, andcodex/qwenreturnfalse. It also requireshostHasBinary(bin)- the agent CLI must be installed on the host.agent_reply.go:86-94), builds the research prompt (replyResearchPrompt,agent_reply.go:187-222- this is the exact prompt you are reading right now), thencaptureReplyResearch(agent_reply.go:165-183) runs the argv viacapturePreflight(agent.go:612-621) in a throwawayos.MkdirTempcwd, bounded by the level timeout.runAgentReplygets ahostForgejoClientand callscommentIssue(...)host-side (agent_reply.go:114-120), wrapping the read in a header +<!-- ward-agent-reply -->footer (replyComment,agent_reply.go:230-247).replyResearchPromptis optional - the in-prompt agent maygit cloneinto scratch if depth warrants, but nothing is provisioned.Freeform mode (bare quoted question) →
runAgentAsk(agent_advisor.go:84-160). This is a fresh attached ephemeral container:--repo(or infers from cwd git origin,agent_advisor.go:96), trust-gates the owner, decidesoneshotfrom--oneshot || !terminalAttached()(agent_advisor.go:109), and seeds eitherinteractivePrompt(default TTY session) oraskPrompt(agent_advisor.go:111-114).writeContainerAssets()+buildUpPlan(...)(agent_advisor.go:116-123,container.go:99-146) build the plan, re-cast asroleAdvisorwith an issueless machine-id name (agent_advisor.go:132-133).plan.Ask = oneshottogglesWARD_ASK.createAgentContainerruns it attached (agent_advisor.go:141-159). Output streams to the terminal. It never posts a comment - the answer's only home is the operator's screen.So the two ref/freeform halves of one command already run on two entirely different execution models, and only ref mode produces a durable issue artifact.
2. Reuse surface for containerizing ref mode
The good news: the container bring-up is already factored, and both existing container paths converge on the same core.
buildAgentPlan(engineer,agent.go:939-963) is literallybuildUpPlan(...)plus a detached/headless re-cast (Role=roleEngineer,Headless=true,Interactive=false,TTY=false,Branch=issue-N).runAgentAsk(freeform advisor) is the samebuildUpPlan(...)core plus an attached/ephemeral re-cast (Role=roleAdvisor,plan.Ask). Both end atcreateAgentContainer(agent.go:1100).What a containerized ref mode would share regardless of which parent it copies:
buildUpPlan→createAgentContainer(the whole plan/mount/pull/envfile spine).ownerAllowed), image flags,--no-pull/--print,writeTokenEnvFile,sweepStaleContainers.maybeForwardAgentDispatchToHostBroker(..., "advisor", ...)(agent_advisor.go:74-76,agent_dispatch_broker.go:292-297) already forwards an in-container advisor ref-dispatch to host ward. That layer is orthogonal to whether the host-side execution is native or containerized.Engineer bring-up vs
runAgentAskbring-up - what differs, and which to lean on:launchAgentContainer,agent.go:983-1043), runs a pre-flight, and emits WARD-OUTCOME. That is a lot of machinery ref mode does not want (no reservation contention for a read-only research pass, noissue-Nbranch, no director reconciliation).runAgentAskis the closer relative: ephemeral, role=advisor, no reservation, no branch, read-only intent. The gap is that it runs attached and streams rather than detached and posts. ItsaskPromptis a "stream to terminal" contract, not a "post a comment" contract.A clean shared extraction would be: keep
buildUpPlanas the base (already shared), and give ref mode a third plan re-cast -roleAdvisorlike freeform, but detached like engineer, carrying thereplyResearchPromptas its seed and a new "post the comment yourself" contract. The thoroughness ladder (agent_reply.go:30-73) is pure and portable as-is - it just needs to map onto a container timeout instead of acontext.WithTimeoutaround a host capture.The one hard constraint that loosens under containerization: the
claude|goose-only restriction andhostHasBinarycheck (agent_reply.go:153-159) exist solely because it runs a host one-shot. In a container the agent binary is baked into the image, so ref mode could gaincodex/qwensupport for free - the same reason freeform mode already supports all four drivers.3. Posting a comment from inside a container
How engineer does it today: the container is never asked by ward to post. The in-container agent posts, as the last line of its own seeded instructions.
headlessReflectionAction(agent.go:101-115) tells the agent that its final step is to post a retrospective comment beginning with aWARD-OUTCOME: done|blocked|failedline. The agent uses the forge token mounted in the container (the same credential it pushes with) to call the forge. Ward's host side never posts - it later reads that comment back (parseBacklogOutcome,agent_director.go:667-711;backlogReconcileparks a container that exited with no WARD-OUTCOME asfailed,agent_director.go:980-1000).Can ref mode post its research comment the same way? Yes, structurally. The clean-container equivalent of
askPrompt/replyResearchPromptwould contract: "research this, then post your answer as a comment onowner/repo#Nand exit." The forge token is already in the container for any writable role, and even a read-only advisor container can post through the credential broker (start_broker/revoke_push_credential,entrypoint.sh:885-890) - the broker keeps commenting ability while dropping push. So a research-and-post-from-inside path is wired-adjacent, not greenfield.The failure-durability angle (ward#402): today's native ref post is a single point of failure. The research lives only in host stdout, and the one
commentIssuecall is the only thing that turns it into a durable artifact. That is exactly what the #306/#401 advisor runs hit - the ward#402commentIssue --body-fileskew meant the host-side post silently failed and the entire research pass survived only in a host dispatch log. Containerizing changes the durability calculus in two ways worth naming for the decision:agent_log_drain.go) rather than a broker log. Marginally more discoverable, not categorically safer.4. Design options
Option A - Minimal: detached advisor container that posts from inside (reuse
runAgentAskbring-up).Add a detached, role=advisor plan variant. Seed it with
replyResearchPromptplus a "post the answer as a comment on this ref, then exit" tail (the ref-mode analog ofheadlessReflectionAction). Ward fires and forgets. Comment-only, no branch.claude|goose-only limit (all four drivers work), gives the clean reproducible tree the issue wants. Isolation win is real.agent_reply.go:121), whereas fire-and-forget means the operator watches the issue, not the terminal. The thoroughness timeout has to move from a hostcontext.WithTimeoutto a container-lifetime cap.Option B - Durable: detached advisor container that commits the research artifact AND posts (reuse engineer bring-up).
Copy the engineer path (
launchAgentContainer→buildAgentPlan), but with a read-only-plus-comment credential posture and a research seed. The agent writes its research to a file on anadvisory-Nbranch (or a commit), pushes it, then posts the comment referencing it, then emits a WARD-OUTCOME-style line.agent_director.go) can observe advisory runs the same way. Strongest isolation and auditability.askPrompt/interactivePrompt. Pulls in reservation/branch/reaper concerns ref mode currently sidesteps. Arguably over-built if the only goal is consistency.Option C - Shared extraction: one
roleAdvisorcontainer helper, comment-only, host-side post-with-fallback.Factor a single advisor-container helper both freeform and ref mode call, parameterized by attached-vs-detached and stream-vs-post. Ref mode runs it detached; the in-container agent researches in the clean tree, then hands the result back and the host posts it (via a broker line or a drained-output contract), with the drained container log as the guaranteed fallback artifact if the post fails. This keeps posting on ward's tested
commentIssuepath (one place to fix ward#402-class bugs) instead of trusting the model to post correctly.replyComment) formatting and any future--body-filefix live in one host-side place rather than in a prompt the model has to obey.Resource cost note (applies to all three): every native ref reply today costs a host process and a temp dir for 3-15 minutes. Every containerized advisory instead costs a full image pull (amortized by
--no-pulland the local cache), a clone of the repo, container create/run, and a writable layer that the stale-container sweeper (sweepStaleContainers, ward#272) later reclaims. For aquick3-minute research pass that may not even clone, that is a large fixed overhead per advisory - a container spun up, cloned into, and torn down to run what is often a few-paragraph answer. This is the resource tradeoff to weigh against the consistency/isolation/durability wins, and it argues for at least keeping--no-pullfast-path behavior and possibly aquick-stays-native carve-out if the overhead proves not worth it for the shallow rungs.Summary for the decision: the container spine is already shared (
buildUpPlan→createAgentContainer), so this is a plan-variant + prompt-contract change, not new infrastructure. The three real forks Kai owns are: (1) reuse the freeform-advisor re-cast (lightest, Option A) vs the engineer re-cast (heaviest, Option B) vs a new shared extraction (Option C), (2) post-from-inside (agent posts, engineer-style) vs host-posts-with-fallback (keeps ward#402 fixes in one place), and (3) comment-only vs also-commit-an-artifact, where only the commit path actually closes the durability gap that motivated the issue. Containerizing also incidentally lifts theclaude|goose-only host-binary restriction, which is a free win forcodex/qwenunder any option.Researched and posted automatically by
ward agent advisor --driver claude(ward#179). This is one-shot research, not a carried change - verify before acting on it.— Claude (she/her), via
ward agentLabeled headless/P3: direction already stated in the body (containerize ref-mode advisor like the other agent modes). Recorded by Claude Code (Fable) during the 2026-07-01 ward launch triage session with Kai.
🔒 Reserved by
ward agent --driver claude— containerengineer-claude-ward-411on hostKAI-DESKTOP-TOWERis carrying this issue (reserved 2026-07-03T06:44:25Z). Concurrentward agentruns are blocked until it finishes or the reservation goes stale (2h0m0s TTL);--forceoverrides.— Claude (she/her), via
ward agent🔒 Reserved by
ward agent --driver claude— containerengineer-claude-ward-411on hostKAI-DESKTOP-TOWERis carrying this issue (reserved 2026-07-03T07:19:32Z). Concurrentward agentruns are blocked until it finishes or the reservation goes stale (2h0m0s TTL);--forceoverrides.— Claude (she/her), via
ward agentWARD-OUTCOME: done - ref-mode advisor now researches in an ephemeral container (host captures its stdout, host-side ward#424 fan-out unchanged). Landed on main, closes #411.
Honest retro: this read as a big architectural fork but collapsed into a small, low-risk change once I traced the primitives. The WARD_ASK freeform container already does most of the work.
claude -pputs the answer on stdout while every bring-up line goes to stderr, so an attacheddocker run -icaptured through the existing dockerCapture hands back exactly the research text. No entrypoint changes, no new capture machinery.The one real design call (named in the commit): only containerize the execution and keep the cross-repo fan-out deterministic host-side. The container researches and streams stdout back, it never posts. That is the research pass's Option C, not "post from inside", because moving fan-out into an in-container agent would trade away the trust-gating for nothing.
What fought back was not the Go but the doc-size cap. agent-advisor.md sat 58 chars under the 4000 limit before I touched it, and the mandatory full-URL issue refs run ~68 chars each, so I spent a few rounds tightening prose back under. Confidence is high on the plan-shaping and gating (unit-tested,
--printrenders the new container framing correctly, all hooks green), medium on the live capture path. I could not safely spin a real nested container from in here, so end-to-end capture is reasoned-and-tested rather than observed.Follow-ups worth filing: ward#402's durability gap is only half-closed (a failed post still loses the research to the container log rather than a branch artifact, which the research pass's Option B would fully close), and now that any wired harness can run ref mode in the sandbox someone should confirm a local model actually honors the structured-JSON emit contract.