design: default-headless intake + tri-role relabel-down discipline #619
Open
opened 2026-07-06 16:58:20 +00:00 by coilysiren
·
3 comments
No Branch/Tag specified
main
issue-1082
issue-1460
issue-1459-daemonless-alias
issue-1454
issue-1453
issue-1301
issue-1443
issue-1283
issue-1447
release
issue-1166
issue-1139
issue-1307
issue-1308
issue-1309
issue-1435
issue-1430
issue-1428
issue-1388
issue-1420
issue-1422
issue-1423
issue-1417
issue-1408
issue-1335
issue-1412
issue-1411
issue-1402
issue-1403
issue-1402-scoop-best-effort
issue-1336
issue-1334
issue-1393
issue-1338
issue-1397
issue-1392
issue-1339
issue-1340
issue-1300
issue-1288
issue-1304
issue-1270
issue-1381
issue-1244
issue-1227
issue-1380
issue-996
issue-1016
issue-1375
issue-1371
issue-1372
issue-1370
issue-1364
issue-1175
issue-1234
issue-1360
issue-1358
issue-1353
issue-1242
issue-1346
issue-1347
issue-1342
issue-1321
issue-1073-rebased
issue-1237-friction-events
issue-1320
issue-1344
issue-1073
issue-1275
issue-1332-replacement
issue-1296
issue-1330-replacement
issue-1224-rebased
issue-1323
issue-993
issue-1243
issue-871
issue-1298
issue-1315
issue-1312
issue-1314
issue-1313
issue-1310
issue-1282
issue-1224
issue-1173
issue-1000
issue-1007
issue-1281
issue-1011
issue-1006-recovery-note
issue-998
issue-1221
issue-1240
issue-1170
issue-1239
issue-1172
issue-1168
issue-1174
issue-1201
issue-1112
issue-1179
issue-1246
issue-1247
issue-1245
issue-1050
issue-1105
issue-1041
issue-1120
issue-1197
issue-1111
issue-1225
issue-1196
issue-1171
issue-1194
issue-1203
issue-1198
issue-1202
issue-1200
issue-1213
issue-1205
issue-1207
issue-1209
issue-1206
issue-1195
issue-1191
issue-1188
issue-1180
issue-1147
issue-1149
issue-1134
issue-1143
issue-1145
issue-1140
issue-1094
issue-1129
issue-1142
stash/agentic-os-image-default-rename
fix/test-env-isolation
docs/features-two-stage-release
fix/promote-server-scheme
fix/smartdefaults-error-source
feat/two-stage-release
issue-1086
fix/placeholder-sentinels
fix/migrate-off-cli-guard-dispatch
fix/test-yml-duplicate-main-gate
issue-1014-landing-fix
issue-911-pr
issue-1109
issue-1008
issue-999
issue-861
issue-1074
issue-1076
issue-1049
issue-1039
issue-994
issue-991
issue-1020
issue-1067
issue-913
issue-982
issue-1034
issue-1005
issue-1031
issue-990
issue-1062
issue-995
issue-1057
issue-905
issue-911
issue-1042
issue-1021
issue-1009
issue-1014
issue-1001
issue-978
issue-985
issue-950
issue-979
issue-977
issue-971
issue-935
issue-970
issue-969
issue-956
issue-965
issue-964
issue-962-restore-readme
issue-951
issue-958-container-config-guard
issue-704
issue-697
issue-896
issue-885
issue-876
issue-895
issue-893
issue-940
issue-923
issue-942
issue-952
issue-952-director
issue-936
issue-937
issue-931
issue-924
issue-920
issue-635
issue-903
issue-892
issue-874
issue-879
issue-890
issue-910
issue-875
issue-897
issue-894
issue-637
issue-842
issue-834
issue-860
issue-541
issue-723
issue-830-github-authoritative
issue-853
issue-634
issue-845
issue-846
issue-843
issue-496
issue-832
issue-777
issue-778
issue-836
issue-700
issue-695
issue-124-share-parser
issue-671
issue-722
issue-694
issue-824
issue-640
issue-735
issue-641
issue-642
issue-818
issue-812
issue-733-clean
issue-804
issue-805
issue-803
issue-735-remove-director-consult
issue-797
issue-801
issue-795
issue-791
issue-790
issue-787
issue-780
issue-737-defer-signoz
issue-732
issue-737-signoz-deferred
issue-734
issue-736
issue-744
issue-769
issue-767
issue-760
issue-763
ward-salvage/ward-c6aa5da9
ward-salvage/ward-94dd7346
issue-729
ward-salvage/ward-58aa3fe3
issue-733
ward-salvage/ward-ff6c509f
ward-salvage/ward-e80f0460
issue-737
ward-salvage/ward-3e2e4760
issue-731
ward-salvage/ward-649addd7
ward-salvage/ward-890e4d29
ward-salvage/ward-645b750b
ward-salvage/ward-bf851a72
ward-salvage/ward-98c8652f
ward-salvage/ward-bb10b620
issue-724
ward-salvage/ward-1ee9be1c
ward-salvage/ward-d18595f6
issue-124
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.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
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.
consult
A human decision, design, or external action must happen first. Fail-closed default for unlabeled/low-confidence.
headless
Agent can take it from open issue to merged change with no human in the loop. The auto-burndown queue.
interactive
Agent does the work but pauses at a human checkpoint mid-flight (design choice, destructive step, human-only verification).
P0
now / blocking / urgent
P1
next / important
P2
backlog / will do
P3
someday / low
P4
icebox / frozen / reopen if it becomes real
No labels
burndown-2026-06
pressure-test
sunday-sprint
coherence-core
consult
headless
interactive
P0
P1
P2
P3
P4
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
2 participants
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/ward#619
Loading…
Add table
Add a link
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?
Intent (Kai)
Flip the intake default so the director files issues
headlessby default, instead of today's fail-closed "unlabeled -> consult". Kai's own guardrail: default-headless is only safe if it is paired with a relabel-down discipline - engineers and advisors must learn to relabel an issue down (headless -> interactive/consult) when they determine it cannot actually be carried autonomously. Without that, "everything ends up incorrectly headless."This is a design brief, not an implementation ticket. Post a concrete plan as a comment for Kai to approve before any implementation dispatches.
Current state (fail-closed - this inverts it)
cmd/ward/agent.go:583-626, ward#607 / agentic-os#246):modeCeilingLevels = [consult, interactive, headless]; an unlabeled issue isconsult (unlabeled default), the floor.agentSurfaceCeilinggates only the engineer role atheadless; director and advisor are ungated.cmd/ward/agent_director_triage.go): a startup pass surveys open issues missing a mode label and promotes only a confident headless/interactive;triageModefails closed to consult otherwise. The consult/interactive/headless definitions the survey uses are the prompt at lines 171-176 - reuse them as the shared vocabulary.OpFileIssue, currently stamps no label - this is what forces--forcetoday), and the freeform intake that files-then-carries (cmd/ward/agent_route.go).Design questions to resolve in the plan
headlessat creation, and how it interacts with the existingtriageModepass. Does default-headless replace fail-closed triage, or only seed the label that triage/agents then correct? Name the interaction explicitly - do not leave two systems fighting over the same label.headless, setinteractiveorconsult; who acts (an engineer that hits the wall mid-run; an advisor whose research concludes the issue is human-gated); and the escalation shape (post a comment explaining why it was downgraded, then stop - never--forcea bad autonomous change past the wall).agentSeedPrompt/role bodies inagent.go,agent_engineer.go,agent_advisor.go), the wardAGENTS.mdcontainer doctrine, or a skill. Capability check: engineers/advisors hold a write-tier token directly (not the broker), and the ward-kdl write guardfile already grantscan add/set/remove issue-label- confirm the advisor role's tier actually includes issue-label add/remove, and flag it if not.Dependency note
The director read-only surface relabeling through the broker needs cli-guard#193 / ward#618 (the broker label op). Engineers and advisors do not - they relabel directly with their own token. So Piece 1 does not block on the broker work; call that out so the plan does not over-couple.
Deliverable
A comment carrying: the resolved answers to the five questions above, the recommended decomposition into landable engineer issues (with the exact doctrine text to add and the files each touches), and an explicit call on whether the fail-closed -> fail-open inversion is worth it or whether a middle path (e.g. default-headless only for a trusted intake class) is safer.
🔎 ward agent advisor
ward agent advisor --driver clauderan a one-shot standard research pass on this question:Design: default-headless intake + tri-role relabel-down discipline
TL;DR recommendation: land the relabel-down discipline (Piece 1) first and unconditionally - it is additive and correct even under today's fail-closed default. For Piece 2, do not flip the broad LLM-judged backlog default to fail-open. Take the middle path: default-headless only for the trusted intake class (issues the director itself files in the act of dispatching them), and leave the backlog-survey (
triageMode) fail-closed. That captures Kai's intent ("the director files issues headless by default") on exactly the issues where headless is safe, without headless-stamping a heterogeneous backlog the moment the discipline ships.Capability confirmed (the one blocking question): yes - both the engineer and the advisor in-container hold a write-capable
FORGEJO_TOKENand the embeddedward ops forgejosurface includesadd/set/remove issue-label(cmd/ward/opsassets/forgejo.guardfile.generated.kdl:247-249, mirroring the write guardfile at.ward/ward-kdl/ward-kdl-write/ward-kdl.forgejo.write.guardfile.kdl:70-74). The advisor container is filesystem-read-only (plan.ReadOnly = true, no git push wiring) but that removes only code-push, not forge-label capability - a label add/remove is a forge API call throughward ops forgejo, not agit push. So an advisor can relabel down and comment with no code change. The only path that cannot relabel is the director read-only surface via the broker (writeTierOpsincmd/ward/broker_exec.go:160-165is FileIssue/EditIssue/CommentIssue/Dispatch only - no label op), which is exactly the cli-guard#193 / ward#618 dependency the issue flags.Answers to the five design questions
1. Scope of "headless by default" - and the two-systems interaction
There are three distinct filing/labeling surfaces today, and they must not fight over the label:
agent_director_triage.go) - a host-side LLM survey that promotes only a confident headless/interactive andtriageModefails closed to consult (lines 85-92). Usescl.addIssueLabelsdirectly, fully capable.agent_route.go) - files an intake record + a scoped child via the host client (signed.createIssue), then carries the child headless. It stamps no mode label on the child today.OpFileIssue, which stamps no label (this is what forces--forceon the follow-on engineer dispatch, sinceissueModeCeilingreads unlabeled asconsultand the engineer ceiling gate wantsheadless).Named interaction (no fighting): keep
issueModeCeiling's unlabeled default fail-closed toconsultas a permanent defense-in-depth floor (an issue that somehow escapes labeling stays gated, never silently headless). Default-headless is a seed at creation on the filing paths, not a change to how the ceiling reads an unlabeled issue. Agents are the only downward-correction mechanism after that. This gives one writer per moment (filing stamps headless, agents relabel down) and one reader (the ceiling gate), never two systems racing on the same label.Recommendation on which paths stamp headless:
agent_route.go, host-sideaddIssueLabelsright after the child is created) - it is already carried headless, so labeling it headless just makes the forge state honest and removes the--forceneed on any re-dispatch.triageMode's backlog default. Do not invert it to fail-open (see the verdict below).2. Downgrade criteria (single-sourced to the triage vocabulary)
The canonical consult/interactive/headless definitions live in
triagePrompt(agent_director_triage.go:170-176). Extract them into an exported Go const (modeLadderDefs) sotriagePrompt, the seed prompt, and the doctrine all cite one source. An engineer/advisor downgrades out ofheadlesswhen any of these hold (each anchored to a ladder rung):These are the same signals the container doctrine already treats as walls ("run until a wall worth a human"); relabel-down is what an agent does at that wall instead of
--force-ing past it.3. Downgrade mechanics + escalation
Who acts:
Mechanics (in-container, token already present, no broker):
(On a GitHub target:
gh issue edit <N> --remove-label headless --add-label interactive.)Escalation shape: post a comment naming the exact signal that made it un-headless, then stop - do not commit a partial/speculative change to "make progress", and never
--forcepast the gate. A downgraded issue is a handoff to a human, and the comment is that handoff. This is a floor-only move: relabel down only. Relabeling up toward headless to clear the dispatch gate for yourself is forbidden - raising the ceiling is the director's or a human's call.4. Where the per-role instruction lives
One primary home, read by all three roles, plus thin pointers:
cmd/ward/containerassets/AGENTS.container.md(the embedded container doctrine mounted into every role's container bywriteContainerAssets). Exact text below. This is the one file all three roles reliably read.modeLadderDefsconst into the seed viaagentSeedPromptWorkflow(cmd/ward/agent.go) for engineer/direct headless runs, and intoaskPrompt/interactivePrompt/replyResearchPrompt(agent_advisor.go,agent_reply.go) for the advisor, so the ladder definitions are never re-authored in prose.docs/agent-dispatch-contract.mdgets a cross-link, and a shortdocs/relabel-down.mdwalkthrough completes the docs trifecta.Capability check result: no guardfile change needed. Both engineer and advisor already carry the
issue-label add/set/removesurface + a live token in-container (confirmed above). The doctrine just needs to hand them the exact command. Flag: the director surface (broker) genuinely lacks the op - that stays a ward#618 item and is out of scope for Piece 1.5. Safe decomposition (prerequisite ordering)
Kai's framing is right: Piece 1 gates Piece 2. Recommended landable engineer issues, in dependency order:
Issue A - Piece 1: tri-role relabel-down doctrine + single-sourced vocabulary (no dependency; safe and good even today)
cmd/ward/agent_director_triage.go- extract lines 170-176 intoconst modeLadderDefs;triagePromptreferences it (pure refactor, no behavior change).cmd/ward/containerassets/AGENTS.container.md- add the "Relabel an issue down" section (exact text below).cmd/ward/agent.go-agentSeedPromptWorkflowinjectsmodeLadderDefs+ a one-line relabel-down pointer on headless runs.cmd/ward/agent_advisor.go+cmd/ward/agent_reply.go- add the relabel-down clause toaskPrompt/interactivePrompt/replyResearchPromptso the advisor relabels down + comments when research concludes human-gated.docs/agent-dispatch-contract.md(cross-link) + newdocs/relabel-down.md; updatedocs/FEATURES.md.agent_test.go/agent_director_test.goto assert the seed carries the relabel-down clause and the extracted const.Issue B - Piece 2 (middle path): stamp headless on the director's own intake (depends on A)
cmd/ward/agent_route.go- after the child issue is created (line 134),signed.addIssueLabels(ctx, target.Owner, target.Name, childNum, []string{"headless"}), best-effort like triage.triageModefail-closed - add a code comment recording that this is deliberate (the middle-path call), so a later reader does not "finish the inversion" by accident.Issue C - cli-guard: broker label op (separate repo; unblocks the director-surface capture path only)
coilyco-flight-deck/cli-guard- add a label op to the brokerOpset + Executor/Authorizer (cli-guard#193). Downstream ward#618 then wiresbroker_exec.gowriteTierOpsto serve it and the director surface stamps headless at capture. Piece 1 does not wait on this - engineers and advisors relabel with their own token, per the dependency note.Exact doctrine text for
AGENTS.container.mdAdd after the "Where the wall still is" section:
The advisor is read-only for code, not for the forge - it may add/remove a label and comment. Frame the advisor's clause accordingly ("if your research concludes the issue is human-gated, relabel it down and say why in your posted answer").
The verdict: is the fail-closed -> fail-open inversion worth it?
Partially - take the middle path, not the full inversion.
--forcefriction. This is the core of Kai's intent and it is safe once Piece 1 exists.triageMode's backlog-survey default from consult to headless. That is a fail-open change over a large heterogeneous backlog judged by a low-confidence LLM pass - precisely the "everything ends up incorrectly headless" failure Kai names, and the relabel-down discipline only catches issues an agent actually gets dispatched on, not the long tail that sits labeled-but-untouched. Keep the confident-promotion behavior; keep the unconfident default at consult.Net: the inversion is right where the label is a byproduct of a fresh, deliberate dispatch decision, and wrong where it is a bulk guess about dormant backlog. Piece 1 (relabel-down) is unconditionally worth landing first; Piece 2 should be scoped to the trusted intake class only.
Awaiting Kai's approval before dispatching implementation. On approval, the recommended firing order is Issue A, then Issue B, with Issue C (cli-guard#193 / ward#618) tracked in parallel since Piece 1 does not block on it.
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 agentScope extension: the dormant-backlog half of the same discipline (from a live incident)
Kai raised this after a director lost its dispatch-broker connection mid-drain and a follow-on seat re-fired the "ready" batch. The postmortem is the argument for widening #619, so it belongs here rather than in a fresh ticket.
What happened. A read-only director surface re-dispatched engineers on issues that still carried a
headlesslabel from an earlier triage flip. Several were old (filed hundreds of issues behind HEAD), two were already closed, and the dispatches passed--no-preflight. Two runs finished and pushed tomainbefore they were stopped by hand. Not harmful, but awkward: an engineer rewrote live code against a stale premise, and one landed via a duplicate of #617.Root cause (one bug, three faces). A freshness judgment gets cached at some earlier moment and trusted at dispatch without rechecking current reality:
headlesslabel is cached at triage.director-startup-triage.mdline 39-40 makes it policy: "presence of a label is the freshness signal, no time-based re-triage." A stamp never expires.--no-preflightcaches "I decided this is GO" with no tie to the code state it was judged against.#619's relabel-down discipline fixes freshness for issues an agent gets dispatched on. The advisor plan above says so directly: it "only catches issues an agent actually gets dispatched on, not the long tail that sits labeled-but-untouched." That long tail is exactly what bit us. So #619 should grow three more pieces, all instances of compute freshness at dispatch, not at triage:
Piece 3 - dormant-backlog drift re-triage (closes the "no time-based re-triage" hole)
Invalidate a mode label when the code it was judged against has drifted, and re-judge. Drift, not wall-clock (time is a weak proxy): stamp each triage label with the HEAD commit or issue-number it was computed at, and when the distance since exceeds a threshold, drop the label back into the untriaged pool so the startup pass re-judges it. This is the minimal change to
agent_director_triage.go's skip-already-triaged rule: skip a labeled issue only while its stamp is within drift tolerance, not forever.Piece 4 - pre-flight hardening + retire the wholesale skip
--no-preflightcan never skip: the issue must be open (a closed issue is an automatic NO-GO - nothing should have dispatched an engineer at a closed ticket), plus the Piece 3 drift check.--no-preflightexists to route around: pre-flight must reason from the resolved repo, not the host dispatcher cwd (the goose-wrong-cwd NO-GO). Fix the gate and the bypass loses its reason to exist.Piece 5 - director per-dispatch effort estimate (builds on the now-landed #617)
#617 shipped static per-role effort (director high, engineer medium, baked in the fleet KDL). Add a dynamic layer: the director emits an effort guess for this ticket at dispatch, overriding the role default. The value is the forcing function - producing the estimate requires a fresh read that sizes the ticket, which is the same medicine as mandatory pre-flight. A refused or low-confidence estimate is itself a hold signal: "I can't size this" means "I do not understand it well enough to fire it," so downgrade to consult rather than dispatch.
Sequencing. Piece 1 (relabel-down) still lands first and unblocks the rest. Pieces 3-5 are independent of each other and of the broker label op (#618). Piece 4's open-state floor check is the smallest and highest-value single fix - it alone would have stopped today's worst case.
Housekeeping fallout from the incident: #617 is now superseded by the #620 merge (per-role config landed); it needs closing, and the landed director effort value needs a check (it may have captured the pre-correction
mediumrather than the correctedhigh, since the engineer freezes the issue body at launch).Correction to Piece 1's capability claim (from the #621 relabel attempt)
The advisor design above states engineers/advisors can relabel with their own in-container token and do not need the broker label op for relabel-down. Empirically that is false for a run dispatched from the read-only director surface: a ref-mode advisor at #621 had every
issue-label add/removerefusedout of tier- its writes route through the broker, not a direct token. So either (a) surface-originated dispatches are broker-gated where normal host dispatches are not, or (b) the direct-token claim is wrong generally. This needs verifying, because it decides whether the director-surface relabel-down path is blocked on #618 after all. Until resolved, treat #618 as load-bearing for any relabel that originates from the director surface.