Watch
2
[epic] Config-driven ward: one precompiled binary, personal config resolved live from a git ref (supersedes the build-variant matrix) #650
Closed
opened 2026-07-07 23:40:21 +00:00 by coilyco-ops
·
6 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
1 participant
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#650
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?
Goal
Replace the emerging "two build variants" release matrix (neutral ward vs coilyco-embedded ward) with a single precompiled binary whose personal configuration is pure config, resolved live from a git ref. This supersedes the build-time-overlay direction of ward#503 step 3 (#644) and the build-from-source tap overlay (homebrew-tap#3). Decided with Kai over the 2026-07-07 director session.
Settled decisions (do not re-litigate - design within these)
coilyco-flight-deck/agentic-os, the.ward/bundle), an external user's own repo for them. Holds guardfiles + fleet and all topology that is currentlyWARD_*env vars (forge base, SSM paths, ollama/signoz endpoints, clone base, target, etc.).forgejo.coilysiren.me/coilyco-flight-deck/agentic-os@main//.ward- enough to fetch on its own.--bundle/file://) is a secondary escape hatch added later.Why this is a small lift (grounding, verified 2026-07-07)
cmd/ward/ops.go(specverb.Build) andcmd/ward/wardkdl_exec.go(execverb.Build) read guardfile + spec-lock bytes from anembed.FSand build the verb surface live. The compiler is already in the shipped binary. The only hard-wired thing is the source:opsAssets/execAssetsareembed.FS, but the build paths takefs.ReadFile/fs.ReadDir, which work over anyfs.FS. Swappingembed.FSforos.DirFS(<synced local copy of (2)>)is the core change.--config>$WARD_CONFIG> walk-up, loud-fail on a set-but-missing override (docs/config-discovery.md). Extend that same pattern to the KDL bundle.Hard non-goal (parked - do NOT open this)
What the neutral default (1) actually contains. This drifts immediately into "seed" / template-repo territory, which Kai wants kept out of this design. Treat the neutral default as an opaque placeholder: the architecture needs only "a safe minimal default exists," never its contents. Design around it. Do not propose seed/template-repo structure.
What the advisor must resolve
gitbinary, lighter, fits a self-contained binary, forge archive API) vsgitshell-out (any ref, private repos via existing creds). Recommend one, with reasoning.host/owner/repo@ref//subpath) and how ward parses it.WARD_*topology values into the KDL bundle without breaking the container/infra that sets them today (staged, backward-compatible).Deliverable
A written design proposal posted to this issue: the resolution of the six items above, the config-resolve architecture (source selection, live sync + cache, launch-time compile from the resolved
fs.FS), the topology-fold plan, and the superseding issue breakdown. Ground every claim in the actual tree (read ward'scmd/ward/*.goconfig/compile/sync paths and aos's.ward/bundle).Related
aos#332 (KDL source, in flight), #644 (build overlay, superseded), homebrew-tap#3 (tap overlay, dropped), ward#645 (neutralize, folds in), #503 / #453 (the cutover), #441 / #395 (why coilyco values were externalized), #539 (ward-kdl -> ward migration). Filed from the read-only director surface (she/her).
🔎 ward agent advisor
ward agent advisor --driver clauderan a one-shot standard research pass on this question:Config-driven ward: design proposal (ward#650)
Grounded in the current tree:
cmd/ward/ops.go,cmd/ward/wardkdl_exec.go,cmd/ward/fleet.go,cmd/ward/container_bootstrap.go,cmd/ward/container_compute.go,docs/config-discovery.md,docs/container-env.md,docs/container-substrate.md. All six open items resolved inside the settled decisions. The neutral default stays an opaque placeholder throughout - nothing here touches its contents.The core change, confirmed against the tree
The epic's grounding holds. The KDL compiler is already in the shipped binary and already reads through an
fs.FS:buildForgejoOps(ops.go:62) doesopsAssets.ReadFile(...)->guardfile.Parse->specverb.Build.opsAssetsis//go:embed(ops.go:30).mountWardKdlExec(wardkdl_exec.go:29) doesfs.ReadDir(execAssets, execAssetsDir), thenexecAssets.ReadFile->execverb.Parse->execverb.Buildper file.execAssetsis//go:embed(wardkdl_exec.go:22).fleet.goparsesfleetGeneratedKDL(//go:embed) viafleetconfig.Parse.Every read is
fs.ReadFile/fs.ReadDiragainst anembed.FS. Both satisfyfs.FS, so the only hard-wired thing is the source handle. The change is to make the three build sites take anfs.FSchosen at launch:embed.FS(today's exact behavior, the neutral default).os.DirFS(<synced local checkout of the bundle subpath>).That is the whole behavioral pivot.
specverb.Build/execverb.Build/fleetconfig.Parseare unchanged.1. Fetch transport: git shell-out (recommended)
Recommend
gitshell-out over a bare mirror, not the forge archive-tarball API. Reasoning grounded in the tree:gitfor exactly this.warmSubstrateRepo(container_bootstrap.go:900) doesgit clone --mirrorthengit -C <mirror> remote update --prunethen a workinggit clone.seedExternalContextMirrors(agent_context_seed.go) doesgit clone --mirrorinto the gitcache volume.git_clone.go/git_auth.goalready own authenticated clone. Adding an archive-download path is net-new surface competing with machinery that already exists and is drift-tested.git fetch/git clone --mirrorresolves all three uniformly. Forge archive APIs are inconsistent here: Forgejo/Gitea archive-by-sha support and pathing differ from GitHub's, and pinning to a sha (the operator's integrity story) is a first-class git operation but a second-class archive one.coilyco-flight-deck/agentic-osbehind the same Forgejo the binary already authenticates to for releases (WARD_FORGEJO_BASE,forge.go:45). git shell-out reusesgit_auth.go. An archive API path would need its own token plumbing.git, and the bundle-resolving consumer is Kai's fleet, not a bare external adopter. External adopters use a local.ward/ward.yamlplus the baked neutral default and never resolve a remote bundle at all, so they never need git for this path.Escape hatch (decision 3, secondary): a
file:///--bundle <dir>form skips git entirely and handsos.DirFS(dir)straight to the build sites. Land it after the git path.2. Refresh cadence + the exact reuse target
Reuse target, named precisely: the substrate warmer in
cmd/ward/container_bootstrap.go-warmSubstrate(:940),warmSubstrateRepo(:900), andsubstrateMirrorStale(:889) - driven byWARD_SUBSTRATE_TTL(default 600s,container_compute.go:636,docs/container-substrate.md). Its properties are exactly what a hot-path config gate needs:substrateMirrorStalestats<mirror>/FETCH_HEADand calls it stale only oncenow - mtime >= ttl. A missing FETCH_HEAD (fresh clone/hydrate) is fresh. So a burst ofward exec buildcalls inside the TTL window does zero network I/O.flockserialization.warmSubstrateRepowraps the ensure-and-freshen inr.withFlock(lock, ...)(cli-guardpkg/flock, importedcontainer_bootstrap.go:19), so concurrent ward processes racing the same mirror do not corrupt it.remote updatefailure it logssubstrate: refresh failed ... (using cached state)and proceeds on the cached mirror. That is the offline story verbatim.Proposed factoring: extract the mirror-ensure-and-freshen core of
warmSubstrateRepointo a sharedsyncGitRef(ctx, spec, ttl)that returns a local working-checkout path, and have both the substrate warmer and the new config-bundle resolver call it. Same TTL gate, same flock, same cache-fallback, one code path.Trigger + cache location: resolve-on-launch, TTL-gated. On host, cache the bundle mirror + checkout under
~/.cache/ward/config-bundle/<hash-of-ref>/(sibling toconfig.CacheDir, referenced inagent_log_drain.go:146); in a container reuse theward-gitcachevolume the substrate warmer already uses. TTL default 600s to matchWARD_SUBSTRATE_TTL, overridable by a newWARD_CONFIG_TTL. First resolve populates the cache, then the FETCH_HEAD gate keeps hot-path invocations network-free. Because the checkout is a real directory,os.DirFS(checkout/<subpath>)feeds the build sites with zero further copying.3. The var grammar
Proposed var name
WARD_CONFIG_REF(parallelsWARD_CONFIG, which already selects the allowlist perdocs/config-discovery.md). Grammar, go-getter / Terraform-module style so the//subpath split is unambiguous:<host>/<owner>/<repo>[@<ref>]//<subpath>Example from the epic:
forgejo.coilysiren.me/coilyco-flight-deck/agentic-os@main//.wardParse order (self-describing, no forge assumptions):
//-> left = repo-spec, right =subpath(.ward).//cannot appear in a host/owner/repo, so the split is safe.leftonce on@->repospec(host/owner/repo) +ref(main). No@->refdefaults toHEAD/ the remote default branch.https://<repospec>.git.refis passed to git untouched - branch, tag, or sha, ward does not classify it (decision 3).fs.FSisos.DirFS(filepath.Join(checkout, subpath)).Parsing is a ~20-line pure function with a table-driven test, mirroring the shape of
parseConfigOverrides(container_compute.go:576).4. Topology fold: the ~14 WARD_* values into the bundle
The fold is a small, staged, backward-compatible step because the fleet already treats these as env-over-baked-default DATA, not identity.
container_compute.go:100already says so: "Tailnet + tower topology (ward#395): infra DATA, not baked identity. Each value takes a WARD_* env override, the old literal kept as the fail-safe default." And ward#616 already resolves--config agent.<name>.<key>into WARD_* env keys (configEnvKeys,container_compute.go:555). The bundle just becomes a third, middle tier in an ordering that already exists.New precedence (a strict superset of today's
env > baked default):WARD_* env > KDL bundletopologyblock > baked neutral defaultNothing that sets an env var today changes behavior - env still wins. The bundle only fills the slot the baked coilyco literal fills now.
The values to fold (from
docs/container-env.md+ the code), each with its current hard-wired home:forgejoBaseURL = "https://forgejo.coilysiren.me"(forgejo_ops.go:23),WARD_FORGEJO_BASE,WARD_FORGE/WARD_CLONE_BASE.value ssm "/forgejo/coilyco-ops/api-token"(opsassets/forgejo.guardfile.generated.kdl:18), resolved byforgejoTokenResolver/ssmValueResolver(ops.go:112,:381).WARD_TAILNET_NETWORK(ward-tailnet),WARD_TAILNET_PROXY(mac-proxy:1055),WARD_TOWER_HOST(kai-tower-3026),WARD_TOWER_OLLAMA_PORT(11434) - thedefault*consts atcontainer_compute.go:104-127.WARD_OLLAMA_URL,WARD_TOWER_OLLAMA(towerOllamaURL,:151).WARD_SUBSTRATE_SEED/_DEST/_MANIFEST/_TTL(container_compute.go:633-636).Staging (no flag-day):
topologysection to aos's.ward/bundle (aos#332), add the bundle-resolve path, and insert the bundle tier between env and baked default in each resolver (envOr->envOrBundleOr). Baked defaults and every WARD_* env override stay intact. A run withWARD_CONFIG_REFunset is byte-for-byte today.container_compute.godriver and infra atWARD_CONFIG_REF. The container path that sets these WARD_* vars for children (wardEnv,container_compute.go:605) resolves them from the bundle first, then still passes them through as env, so the in-containerentrypoint.shandcontainer_bootstrap.goare unchanged - the env contract indocs/container-env.mdis preserved as the transport, the bundle just becomes its source. The now-redundant literal env sets become harmless.5. Integrity + fail-loud (mechanism, not policy)
ward does not police which ref (decision 3), but it fails loud whenever the named source cannot resolve, consistent with
docs/config-discovery.md's set-but-missing override rule. The behavior matrix:WARD_CONFIG_REFunset -> baked neutral defaultembed.FS. Never an error. This is decision 4's trivial precedence.//, empty subpath, empty repospec) -> fail loud naming the exact grammar violation, before any network. Same spirit asparseConfigOverrides' loud unknown-key error.using cached state). Offline resilience, not a hard fail, because the operator's intent (use the bundle) is still honored.opsCommand(ops.go:42) catches a build error and mounts a leaf that surfacesguardfile runtime failed to mount: %won invocation. Reuse that exact degrade-to-error-leaf pattern so a bad bundle cannot silently drop a whole verb surface.repo_rootperAGENTS.mdSafety), so every guarded invocation is attributable to the exact bundle commit it compiled from.6. In-flight reconciliation + superseding issue breakdown
.ward/. This design's Stage 1 adds atopologysection to that same bundle. It is the upstream dependency for everything below: the ward-side resolver has nothing to resolve until the bundle exists.AGENTS.mdRelease, wherebump-tap-formulaalready rewrites the formulaurl+sha256to a released artifact - keep that, drop any from-source path).Concrete replacement issue list (all land in
coilyco-flight-deck/ward, filed off this epic; ordered by dependency):ops.gobuildForgejoOps+graftForgejoAdminExec,wardkdl_exec.gomountWardKdlExec,fleet.goloadFleetConfig) take anfs.FSselected at launch:embed.FSwhenWARD_CONFIG_REFis unset (neutral default),os.DirFS(resolved subpath)when set. Reuse theopsCommanddegrade-to-error-leaf on parse failure. Depends on aos#332 for a real bundle to point at (tests usefile://fixtures).WARD_CONFIG_REFgrammar + the sharedsyncGitRefTTL-cache resolver. Thehost/owner/repo@ref//subpathparser (pure, table-tested) plus the git shell-out resolver factored out ofwarmSubstrateRepo(TTL gate viasubstrateMirrorStale,withFlock, cache-fallback). Delivers thefs.FSthat issue 1 consumes. Depends on issue 1'sfs.FSseam being in place.topologysection to the bundle and insert the bundle tier into eachenvOrresolver (env > bundle > baked default), Stage 1 pure-addition first. Depends on issues 1+2 (needs the resolved bundle) and on aos#332 carrying the section.Escape hatch, deferred:
--bundle/file://local-file mode (decision 3, secondary) as a follow-up once the git path lands - it is a trivial branch in the issue-2 resolver (os.DirFSdirectly, no sync).Summary of the recommendation
One prebuilt binary,
fs.FSchosen at launch behind the existing config-discovery precedence, resolved live viagitshell-out over a bare mirror through the substrate warmer's TTL+flock+cache-fallback machinery (warmSubstrateRepo/substrateMirrorStale),WARD_CONFIG_REF=host/owner/repo@ref//subpath, topology folded in as anenv > bundle > baked-defaultmiddle tier that supersets today's ward#395 ordering, and fail-loud on an unresolvable-and-uncached named source per config-discovery. Every claim ties to a specific site in the current tree, and no part of it opens the neutral-default-contents question.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 agentIn-flight reconciliation + filed breakdown (director surface, 2026-07-08)
The design comment above was written from-scratch and assumed aos#332 was still in flight. Reconciling against the current tree and constellation, with the breakdown now filed as real issues.
The linchpin already landed
aos#332 merged 2026-07-08 (top of aos
main). The design named it the upstream dependency for everything - it is done. aos's.ward/bundle now carries the real guardfiles (ward-kdl.forgejo/ollama/signoz.guardfile.kdl,ward-kdl.fleet.kdl), the openapi/swagger locks,ward.yaml, anddocs/ward-specs.md. Consequences:file://fixtures.container_compute.go(tailnet, tower, ports, substrate topology).Filed breakdown (all in ward, ordered by dependency)
WARD_CONFIG_REFgrammar (host/owner/repo@ref//subpath) + the sharedsyncGitRefTTL resolver factored out ofwarmSubstrateRepo. Blocked on #653.consult). New, raised by Kai reading the landed fleet.kdl. See below.The model-config layer the from-scratch design missed (#658)
The fleet.kdl carries per-agent + per-role model strings (
gpt-5.4,claude-fable-5,claude-opus-4-8[1m],qwen3-coder:30b,gpt-5.5). Under the old baked config these shipped lockstep with the binary that understood them. Under live-resolve, the bundle onmainand the local harness binaries version independently, and models move fast - so a fleet.kdl can name a model the local harness rejects. This is distinct from #656's source fail-loud: the bundle resolves and parses cleanly, but a value inside it is stale for the specific harness. Detection must be per-harness (claude / codex / opencode-against-ollama / goose each reject differently, and a central ward-side allowlist would stale immediately). The fork - fall back to harness default vs fail loud, and where detection lives - is Kai's call and is captured in #658.Folded in / superseded (closing)
go build) - the epic drops build-from-source. Channels become download-and-verify (#657). Closing, superseded by this epic.Coordinate, not close
ward ops) and guardfile-spec section overlap the topology fold (#655). aos#332 already homed those guardfiles. Sequence #655 with #539's verb-surface work.Filed from the read-only director surface (she/her).
coilyco-ops referenced this issue2026-07-08 03:40:46 +00:00
Two more siblings from Kai's live review of the landed
.ward/ward-kdl.fleet.kdl:consult) - built-in defaults for frontier harnesses. The per-agent blocks should compress to smart defaults:agent claude { context-level 2; model ...; reasoning-effort medium }for Kai,agent claude {}for end users, and no KDL entry at all for frontier harnesses (claude/codex/gemini/...). ward carries built-in launch defs, the spec becomes a sparse override layer. Extends ward#616's override-only precedent from model/effort to binary/stream/auth/argv. Sibling to #658 (the value-validity layer under this compression).ward agent --driver->--harness(keep--driveras a deprecated alias). The flag already 'picks the harness' per the help text, and--agentwould collide with the roster noun + theward agentcommand.Filed from the read-only director surface (she/her).
Dispatch PAUSED 2026-07-08 (Kai traveling) - state for a cold pickup
Landed on
main(done):docs/config-source.md).WARD_CONFIG_REFgrammar + sharedsyncGitRefTTL resolver (cmd/ward/gitsync.go).--harnesscanonical,--agentaccepted as equal spelling,--driverdeprecated alias.All three were spuriously reopened by the reaper regression and re-closed by hand - their code is on
main.In flight (let it finish):
.ward-run-provenance.jsonas trailing residual, and the closing-ref gate ignoredrun-owned landed: yes). Fix = exclude the provenance file from the residual snapshot and guard the gate with!landed. The fix run may itself show one more spurious reopen - ignore/close it. The fix propagates to the reaper via release-on-push once a new version is picked up by new containers.Blocked by the pause (unblocked technically, NOT dispatched):
Awaiting Kai's decisions (
consult, no dispatch):Cleanup owed (operator action): ~4 junk
ward-salvage/*branches from this session (provenance-file residual only, no lost work), plus older ones. Branch deletion not done from the read-only surface.Filed from the read-only director surface (she/her).
Status refresh from the read-only director surface:
Done and closed: #653, #654, #655, #656, #657.
Now in flight: #670 (stale model-config launch gates, from #658) and #671 (effective fleet roster / frontier built-ins, from #659). Both have been dispatched to Codex engineers.
Remaining external wall: #646, the frozen GitHub mirror. That still blocks proving the GitHub half of byte-identical release channels, but it is a human credential / mirror-config action, not a ward implementation slice.
Closing as completed. The implementation breakdown recorded in this epic landed through #653 to #657 and follow-ups. Any remaining AOS runtime coupling is now governed by #1622.