Skip to content

Commit 7f1e085

Browse files
chore(release): v0.1.117-rc.4 [skip ci]
1 parent 4a64cde commit 7f1e085

6 files changed

Lines changed: 255 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,256 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
66

77
<!-- changelog:entries -->
88

9+
## [0.1.117-rc.4] - 2026-07-24
10+
11+
12+
### Added
13+
14+
- Feat(cli): health-aware list/stop, startup failure diagnostics, port retry, doctor --probe (#820)
15+
16+
* feat(cli): warn before af stop interrupts running executions
17+
18+
`af stop <node>` gracefully killed nodes with long-running executions in
19+
flight with no warning. Running executions are queryable from the control
20+
plane, so query them before signalling the process:
21+
22+
- running executions found + TTY → list count/ids/age and prompt to confirm
23+
- running executions found + no TTY → warn (count/ids/age) and proceed
24+
- --force → stop immediately, no query/warning/prompt
25+
- control plane unreachable → note it and proceed (best-effort, as before)
26+
27+
The check runs only once we have confirmed the process is genuinely ours and
28+
alive, so a dead/stale node still reconciles cleanly without spurious queries.
29+
30+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
31+
32+
* feat(cli): surface af run startup logs and retry once on strict-port bind conflict
33+
34+
Two operational failures in the `af run` path made a failed start opaque and
35+
non-recoverable:
36+
37+
- On any startup failure the CLI only printed "did not become ready within 30s";
38+
the real traceback/exit reason lived in the node log, reachable only via a
39+
separate `af logs`. Now the last ~15 lines of the node's log are printed
40+
inline on failure, plus a "Full logs: af logs <node>" pointer.
41+
42+
- When a node was assigned a port that looked free but lost the bind race (a
43+
just-stopped node's port lingering under mirrored networking), the SDK exited
44+
with AGENTFIELD_STRICT_PORT "assigned port N is unavailable" and nothing
45+
retried. The run path now detects that strict-port exit from the node log and
46+
retries exactly once on a fresh port (the failed port is reserved first so it
47+
is never reused), logging "Port <p> unavailable, retrying on a fresh port".
48+
49+
The port-alloc/start/wait section is refactored into attemptStart +
50+
startWithPortRetry so the retry decision and port-change logic are unit-testable
51+
without the real health-poll.
52+
53+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
54+
55+
* feat(cli): reconcile af list registry status with control-plane health
56+
57+
`af list` showed only the local registry's view, which is a claim, not a fact:
58+
a node the registry calls "running" can be dead on the control plane (or a
59+
registry "stopped" node can still be live). Add a HEALTH column that fetches the
60+
control plane's node view (GET /api/v1/nodes?show_all=true, so inactive nodes
61+
are included) and reconciles it with each node's registry status:
62+
63+
- statuses agree → plain health (e.g. "active")
64+
- statuses disagree → health + "(mismatch)" and a footer explaining it
65+
- node absent from CP → "not on control plane (mismatch)" when registry running
66+
- control plane unreachable → "unknown (control plane unreachable)", never an error
67+
68+
The same health/health_discrepancy fields are added to `af list --json` for the
69+
agent-driven flow. A missing control plane never fails the command.
70+
71+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
72+
73+
* feat(cli): add af doctor --probe to smoke-test detected provider CLIs
74+
75+
`af doctor` reported a provider as available whenever its binary was on PATH,
76+
but a present binary can still return instant empty completions (broken auth,
77+
model outage) — the doctor called it healthy while every real call failed.
78+
79+
Add an opt-in `--probe` flag that runs a minimal one-shot prompt against each
80+
DETECTED provider CLI (claude -p, codex exec, gemini -p, opencode run) with a
81+
per-provider 60s timeout and classifies the result:
82+
83+
- ok → non-empty completion
84+
- empty → exit 0 but no output (the silently-broken case a PATH check misses)
85+
- error → non-zero exit (stderr head captured)
86+
- timeout → no response within the timeout
87+
88+
Probes run only for providers doctor already detects; without --probe the
89+
command is unchanged. Output and help note that a probe consumes a trivial
90+
amount of provider quota. The classifier is a pure function so ok/empty/error/
91+
timeout are table-tested from (exit code, stdout, timed-out) tuples.
92+
93+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
94+
95+
* fix: preserve explicit agent ports on startup conflict
96+
97+
* chore(skills): sync embedded skill mirrors on branch
98+
99+
Realigns embedded mirrors with skills/ sources inherited from the main
100+
merge so skillkit drift tests pass branch-locally.
101+
102+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
103+
104+
---------
105+
106+
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> (f11cb69)
107+
108+
109+
110+
### Fixed
111+
112+
- Fix(cli): make af config write through to the secret store + pre-install requirements visibility (#819)
113+
114+
* fix(cli): make af config write through to the node-scoped secret store
115+
116+
`af config <node> --set K=V` (and interactive `af config <node>`) only ever
117+
wrote the package `.env`, but `af run` resolves a node's environment from the
118+
encrypted secret store, not that file — so configured values looked saved yet
119+
never reached the running process, and `af config` even told users to run
120+
`af run` with settings it would ignore.
121+
122+
Mirror every value set via `af config` into the node-scoped secret store (the
123+
same one `af secrets set K --node <node>` uses), keeping the `.env` for `af dev`
124+
and the web UI env editor. `--unset` now removes from both destinations so an
125+
unset value cannot linger and get re-injected. Success/interactive copy now
126+
states both destinations truthfully.
127+
128+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
129+
130+
* fix(cli): add actionable fix command to missing-secret startup errors
131+
132+
When a required secret is missing and stdin is not a TTY, `af run` hard-failed
133+
with an error that listed variable names but no way to fix them. Pair each unset
134+
variable (and every option of an unsatisfied require_one_of group) with the exact
135+
command that resolves it — `af secrets set <VAR> --node <name>` — and name the
136+
node in the message so the command is copy-pasteable.
137+
138+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
139+
140+
* feat(cli): add af show-requirements to inspect a node before installing
141+
142+
There was no way to see what environment variables a node needs until after
143+
installing it. `af show-requirements <path-or-git-url>` resolves the source
144+
WITHOUT installing — a local path is parsed in place; a Git URL (with optional
145+
@ref and //subdir selector) is shallow-cloned into a temp directory that is
146+
removed afterwards, so nothing is written under ~/.agentfield.
147+
148+
It prints the node name, required variables, optional variables with their
149+
defaults, and require_one_of groups, pairing each required variable with the
150+
exact `af secrets set <VAR> --node <name>` command. Supports `-o json`. The gap
151+
is now also called out in `af install --help`.
152+
153+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
154+
155+
* fix(cli): point post-install guidance at af secrets + explicit next steps
156+
157+
The post-install output told users to run `af config <node> --set VAR=...` for
158+
missing required variables — a command that only wrote the package .env, which
159+
`af run` ignores. Point it at `af secrets set <VAR> --node <name>` (which `af run`
160+
reads) for both missing required variables and unsatisfied require_one_of groups,
161+
and always print explicit next steps (`af run <name>`, `af list`) so a first-time
162+
user is never left guessing.
163+
164+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
165+
166+
* docs: document af show-requirements and write-through af config
167+
168+
Document the new `af show-requirements` command and the now write-through
169+
`af config` behavior in the agent-node installation guide, consistent with the
170+
existing `af secrets` guidance: `af config --set/--unset` mirrors into the
171+
node-scoped secret store `af run` reads (keeping the `.env` for `af dev` and the
172+
web UI), and the non-interactive missing-secret error now includes the fix
173+
command. Adds both commands to the lifecycle reference table.
174+
175+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
176+
177+
* fix(config): preserve env values and contain subdirs
178+
179+
* fix(packages): report missing --path subdirs as missing manifests again
180+
181+
The symlink-containment hardening made EvalSymlinks fail first on absent
182+
subdirectories, surfacing a raw lstat error instead of the documented
183+
'no agentfield-package.yaml found (expected at <path>)' message and
184+
breaking four tests that pin that contract. Handle not-exist explicitly
185+
before the resolution error path.
186+
187+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
188+
189+
* chore(skills): sync embedded skill mirrors on branch
190+
191+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
192+
193+
* test(cli,packages): cover requirements CLI branches and subdir error paths
194+
195+
Closes the patch-coverage gap: no-configuration and unlabeled
196+
require_one_of rendering plus inspect-error propagation in
197+
af show-requirements, and the root-resolution / manifest-missing error
198+
branches of ResolvePackageSubdir.
199+
200+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
201+
202+
---------
203+
204+
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> (4a64cde)
205+
206+
207+
208+
### Other
209+
210+
- Replace N+1 execution fetches in batch-status handler with one batch fetch (#811)
211+
212+
* issue/batch-status-n-plus-1: replace N+1 execution fetches in batch-status handler with one batch fetch
213+
214+
handleBatchStatus now issues a single GetExecutionRecordsBatch query
215+
regardless of how many execution IDs are requested, instead of looping
216+
GetExecutionRecord per ID. Missing IDs preserve the prior per-ID
217+
'not_found' response. Requests with more than 500 IDs are rejected with
218+
a 400 before hitting storage. Storage layer gains GetExecutionRecordsBatch
219+
on LocalStorage and the StorageProvider/ExecutionStore interfaces; test
220+
stubs updated to satisfy the new interface.
221+
222+
* fix: preserve batch status partial results
223+
224+
* chore(skills): sync embedded skill mirrors on branch
225+
226+
Realigns embedded mirrors with skills/ sources inherited from the main
227+
merge so skillkit drift tests pass branch-locally.
228+
229+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
230+
231+
---------
232+
233+
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> (984996d)
234+
235+
- InMemoryBackend: deep-copy values on Set/Get to fix data race (#807)
236+
237+
* issue/inmemory-deepcopy: deep-copy map/slice values in InMemoryBackend Set/Get and SetVector/GetVector to prevent data races
238+
239+
* test: add deep-copy helper coverage for []any, []float64, nil/default paths
240+
241+
Exercises the previously-uncovered branches in deepCopyAny ([]any
242+
recursion, []float64 copying, default passthrough) and
243+
deepCopyFloat64Slice (nil input handling) to satisfy the patch-coverage
244+
gate at 80%. No production code changes.
245+
246+
* fix(sdk): reject cyclic in-memory values
247+
248+
* chore(skills): sync embedded skill mirrors on branch
249+
250+
Realigns embedded mirrors with skills/ sources inherited from the main
251+
merge so skillkit drift tests pass branch-locally.
252+
253+
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
254+
255+
---------
256+
257+
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> (7793bc8)
258+
9259
## [0.1.117-rc.3] - 2026-07-24
10260

11261

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.117-rc.3
1+
0.1.117-rc.4

control-plane/internal/templates/go/go.mod.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ module {{.GoModule}}
22

33
go 1.23
44

5-
require github.com/Agent-Field/agentfield/sdk/go v0.1.117-rc.3
5+
require github.com/Agent-Field/agentfield/sdk/go v0.1.117-rc.4

sdk/python/agentfield/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,4 @@
181181
"reasoner",
182182
]
183183

184-
__version__ = "0.1.117-rc.3"
184+
__version__ = "0.1.117-rc.4"

sdk/python/pyproject.toml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/typescript/package.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)