feat(agent_sys): AgentsView as the o11y panel - #154
Draft
dorado269 wants to merge 52 commits into
Draft
Conversation
Wire kenn-io/agentsview into agent_sys as its o11y panel: native binary under a ~/.infera_agent_sys prefix owned by env_mgr, session scoping via a child-process-only CLAUDE_CONFIG_DIR, resident daemon on port 18888, and warn-and-skip on every failure mode. Previous task's CLAUDE.md and checkpoint log preserved as .bak. Signed-off-by: yihou <yihou@amd.com>
Phase 0 settles the two unverified facts (install prefix knob, whether claude-agent-sdk honours CLAUDE_CONFIG_DIR) before any dependent code. Phases 1-5 are TDD tasks; Phase 6 is the six-check acceptance on demo2. Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
…is ours Signed-off-by: yihou <yihou@amd.com>
…G_DIR Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Pins the release (v0.42.0, checksum-verified via a private mktemp -d,
never a shared /tmp path) rather than following "latest"; version:
"0.42.0" so check_cmd's output is compared against something instead
of satisfies(actual, None) accepting anything.
target.path is a placeholder per the existing sglang.repo.yaml
convention: neither recipe.py nor the bin installer expand ${VAR} in
a YAML value, so the prefix is supplied via --path at invocation, not
templated in the recipe file. install: expands $AGENT_SYS_HOME (the
one var the documented invocation exports) rather than introducing
$AGENT_SYS_BIN, which nothing in this call chain sets.
Also notes in the design doc that the claude CLI lazily creates
.claude.json, backups/, and sessions/ as siblings of projects/ under
the redirected CLAUDE_CONFIG_DIR root, measured during Phase 0 recon.
Signed-off-by: yihou <yihou@amd.com>
…ment agent_environment() does not put \$AGENT_SYS_BIN on PATH for spawned agent children (bin_on_path=False, prepare.py) -- the recipe comment claimed the opposite. Whatever eventually calls ensure_installed() still needs \$AGENT_SYS_HOME/bin on PATH itself. Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Never raises, one log.warning per failure, same law ensure_running already holds. Reuses level_for_missing (via importance: suggested in the recipe) rather than re-deriving severity: the outcome's own .level decides whether a missing agentsview is fatal. check_cmd is now an absolute $AGENT_SYS_HOME/bin/agentsview path rather than a bare command name -- measured by actually running the recipe three times: a bare name only finds the binary, and thus only reports "already present (skip)" on a second run, if $AGENT_SYS_HOME/bin happens to already be on the caller's ambient PATH, which nothing in this call chain guarantees (agent_environment() deliberately does not put $AGENT_SYS_BIN on PATH for spawned agent children). $AGENT_SYS_HOME is patched into os.environ for exactly the duration of the underlying subprocess calls (run_cmd has no env= parameter) and restored in a finally, verified to hold even when the installer raises. Noted in the docstring as the one caller not yet justifying a shared env= parameter on run_cmd itself. ensure_installed takes the recipe-running step as an injected callable rather than calling load_recipe/runner.run directly: env_mgr spec §9's decoupling wall forbids o11y from importing the installer machinery, enforced structurally by test_imports.py -- a first draft that imported recipe/runner directly failed exactly that test. The caller (left to whoever wires the CLI call site) assembles the callable from outside the wall. Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
…e docs table Five slugs guessed from AgentsView's human-readable provider table were wrong (claude-cowork, command-code, copilot-cli, cortex-code, gemini-cli): serve validates disabled_agents and refuses the whole config on the first bad name, so serve --background exited 1 and the panel never came up -- warned and skipped correctly, but for the wrong reason, caught from a real acceptance run's stderr. Rebuilt OTHER_PROVIDERS from `agentsview doctor sync`'s own "Agent roots:" report (every provider name this installed binary recognizes), minus claude, plus aider (independently confirmed accepted by the config parser though doctor sync prints no root for it in this version). Verified end to end: the full corrected list loads cleanly against the real installed agentsview binary via one health call. Added check_disabled_agents, wired into ensure_installed right after a successful install: writes the real config and runs one health call against it, so a future provider rename is a distinct install-time warning naming the offending slug rather than a generic "serve exited 1" discovered later. One process call against the actual config file, not one per candidate -- the parser already reports one bad name per call, the same way a human debugging this by hand would find them. Never raises, and a bug in the check itself cannot turn a successful binary install into a reported failure (separate try/except from install_item()). No change to ensure_running's failure/retry behavior: still exactly one warning on the servce-failure path, still no fallback to a permissive config -- a dead panel remains the correct outcome of a bad provider list. Signed-off-by: yihou <yihou@amd.com>
…a hardcoded list A hand-maintained OTHER_PROVIDERS has two independent failure modes, not one: a wrong slug kills serve loudly (already fixed once this round), but a provider *missing* from the list fails silently -- AgentsView happily scans that provider's default directory and adds its sessions to the panel, defeating gate 3 with no error at all. Comparing the previous hardcoded list against a fresh `doctor sync` run found exactly this: grok, hermes, iflow, kiro-ide, qoder, warp, zencoder and others were real, currently-recognized providers this list never mentioned. discover_providers(prefix) asks the installed agentsview binary directly (`doctor sync`'s own "Agent roots:" report) and parses every provider name it recognizes, minus claude. This is now the primary mechanism: a provider renamed in a future release is self-correcting (the name comes from the binary, not a stale string), and a provider newly *added* in a future release is picked up automatically the next time the binary is asked, with nobody needing to remember to update a constant. FALLBACK_OTHER_PROVIDERS (the previous OTHER_PROVIDERS, unchanged list) is kept as a last resort only, used by resolve_disabled_agents with exactly one warning when discover_providers can't be trusted (binary missing/crashed/unparseable report) -- never silently, and never an empty list, since "disable nothing" is the single most permissive failure mode this path could produce. write_config now takes the provider list as a parameter instead of reading a module constant, so it stays a pure, easily-testable writer regardless of where the list came from. check_disabled_agents is unchanged in behavior but now mostly guards the fallback path, since the primary path's correctness follows from asking the binary directly rather than needing separate validation. Verified end to end against the real installed v0.42.0 binary: discover_providers returns 59 names (claude excluded), matches resolve_disabled_agents with no fallback triggered, and the resulting config.toml loads cleanly per check_disabled_agents. Diffed against FALLBACK_OTHER_PROVIDERS: the only difference is "aider" (fallback-only, consistent with it being accepted-but-rootless in this version) -- zero real providers missing from the dynamic list. No change to ensure_running's failure/retry semantics: still exactly one warning on the serve-failure path, still no fallback to a permissive config. Signed-off-by: yihou <yihou@amd.com>
Reverts the previous commit's runtime-derived disabled_agents: team lead's call, and the right one -- deriving the list at runtime means a silent upstream AgentsView change silently changes what the panel shows, with no commit, no diff, no review. Worse than a pinned list that occasionally drifts loudly via a check. OTHER_PROVIDERS (renamed back from FALLBACK_OTHER_PROVIDERS) is once again the pinned, hand-maintained, version-controlled source write_config actually uses. discover_providers (doctor sync's own "Agent roots:" enumeration) is no longer the write-time source; it now only feeds check_disabled_agents's completeness direction. check_disabled_agents now checks both ways a hand-maintained list can drift from the installed binary, not just one: - Direction 1 (already existed): a name in OTHER_PROVIDERS the binary no longer recognizes -- breaks serve loudly, the way it broke once already. Caught by running health against the config we wrote. - Direction 2 (new, the one that leaks): a name the binary recognizes that OTHER_PROVIDERS never lists. This loads with zero error -- AgentsView just scans that provider's default directory and puts its sessions on the panel. Caught by running discover_providers and diffing against OTHER_PROVIDERS. check_disabled_agents now returns every offending name (from either direction) in one tuple rather than a single Optional[str], so ensure_installed's one warning at the call site can name all of them at once regardless of how many were found. Sanity-checked the completeness direction the same way as the earlier _patched_environ check: temporarily removed the discover_providers block, confirmed three tests go red, restored it, confirmed green again. Verified end to end against the real installed v0.42.0 binary: write_config(prefix, OTHER_PROVIDERS) + check_disabled_agents returns an empty tuple. Unchanged: no silent fallback in ensure_running, exactly one warning on the serve-failure path with the stderr excerpt. Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
The zone-local CLAUDE_CONFIG_DIR stays: relocating it is what removes the $HOME grant and what harness.harness_env() carries credentials across for. But it also relocated the transcripts, and the panel reads one fixed directory -- measured on demo2, nine agent transcripts landed in nine different <zone>/config/projects/ and the panel showed none. material.deploy now symlinks that one subdirectory to $AGENT_SYS_CLAUDE_HOME/projects. Every attempt has a unique cwd, so each still writes into its own slug subdirectory; sharing cannot collide. Idempotent, repairs a wrong link, replaces an empty directory (rmdir refuses a populated one), and never raises -- one warning and the attempt proceeds. Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
…ement The symlink delivers gate 1 with permissions off, measured on demo2. With AGENT_SYS_NO_PERMISSIONS=0 nothing traverses it, because agent_sys refuses every AI task before the executor starts -- a refusal that predates this feature, confirmed with paired arms differing in one file. The agent_sys limitation itself is recorded outside this spec; only the consequence for this design is here, and it reads 'untested because untestable', not 'safe'. Signed-off-by: yihou <yihou@amd.com>
…= "0s" Measured: the production daemon self-exited twice with no override present, matching AgentsView's own documented default (daemon_idle_timeout, default "20m", documented in configuration.md). Design spec.md promises the panel "persists across runs" and ensure_running/ensure_installed are only ever called from the CLI's own startup path -- with the default idle exit, a user opening the URL an hour after their run ends finds nothing, which is exactly the case the panel exists for. write_config now writes daemon_idle_timeout = "0s" alongside disabled_agents. Confirmed the key does not break config loading (health --limit 1 against it, rc=0) -- though also confirmed via a negative control that this alone is weak evidence, since a completely made-up key is accepted the same way (health tolerates unknown top-level keys; only disabled_agents is strictly validated). The real verification is wall-clock: a background daemon started with this key and zero client traffic, checked after AgentsView's documented 20m default window has passed. That check is running in the background (scratch/idle_probe/data_alive, started 2026-09-03T13:03:39Z); result to follow in PHASE0.md §0.7 and to team lead once it reports. Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Team lead asked whether two concurrent agent_sys deployments on the same box (same prefix, same port, --replace) could kick one another's daemon out from under it. Measured rather than assumed: - --replace against an already-settled daemon on the exact same port still unconditionally kills and restarts it (not a same-port no-op). - ensure_running only reaches --replace after port_is_free(port) is True, so the only window two deployments can both reach it for the same port is a cold-start race (neither daemon up yet). - A synchronized two-thread race against the real binary landed only one actual daemon start; the loser's own serve --replace invocation saw the winner's daemon and did not visibly disrupt it in that run -- recorded as empirical, not a documented guarantee. - Either way, both deployments point at the identical prefix, config, and port, so a replacement swaps one daemon for a functionally identical one serving the same archive: at worst a sub-second connection drop mid-restart, never a lasting outage or different data shown. No code change; this is the docstring team lead asked for so --replace is not later read as an unexamined bug. Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
The smoke test proved the session was servable via GET /api/v1/sessions and we read its documented one-shot exclusion as 'the panel is broken'. It was not: a real browser loading the plain / renders the session, because the web UI's session list calls sessions/sidebar-index and sends include_one_shot=true in its own request. Confirmed by reading a rendered page, twice. The load-bearing assertion is now the browser's request. The CLI surface is pinned separately -- the two endpoints disagree today and a release moving either default should fail a test, not surprise an operator. Identity is still checked on the raw endpoint, which is the only one carrying first_message. Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
zonelink measured it: agentsview health (and projects, and session list) silently autostarts a background serve daemon on a port AgentsView itself auto-discovers, exactly the "port decision made by agent_sys, never delegated" rule this whole component exists to hold -- happening on check_disabled_agents's read-only validation path, which nobody watching ensure_running would ever notice. Reproduced independently by counting real `agentsview serve` processes by exact argv before/after each subcommand: --version and doctor sync start nothing; health starts one, landing on 8083 in one run because 8080 was already taken by another stray from the same bug. AGENTSVIEW_NO_DAEMON=1 (documented for exactly this) was measured next and rejected: it also disables *direct* SQLite reads for health, projects, and session list, even against an already-populated database -- the check would go from "silently starts a daemon" to "always fails", which is worse, not better. Measured, not assumed. The actual fix: doctor sync validates disabled_agents with the identical "unknown session provider" error health produces, and never starts a daemon in either the config-valid or config-invalid case -- confirmed by the same before/after process count. check_disabled_agents now runs doctor sync exactly once, testing both directions from its single result: a non-zero exit with that error is direction 1 (renamed/removed provider); a clean exit's own "Agent roots:" report, diffed against OTHER_PROVIDERS, is direction 2 (added provider we never listed). health is not called at all anymore. Trade-off, recorded in the docstring: a doctor sync that fails never reaches the point of printing Agent roots, so a config with both a stale entry and a missing one only reports the stale one per call -- fixing it and re-running finds the missing one next. The two-probe design could report both problems from one call; traded that away for never starting a daemon on a validation path. Found and cleaned up while investigating: three orphaned agentsview daemons already existed on the real shared prefix (ports 8080/8081/8082, none on our intended 18888), accumulated from repeated triggering of this exact bug across the team's testing. `serve stop` only knew about the most recently tracked one; the other two were unreachable by any documented command (verified: `serve status` reported only one, and after stopping it, "No agentsview server is running" despite two more still listening and answering /). Stopped those two by their exact, individually-verified PIDs -- confirmed via `ps` immediately before, never a pattern-matched kill -- since AgentsView's own tooling had no way to reach them. Verified end to end against the real installed v0.42.0 binary: check_disabled_agents(prefix) -> () with zero new agentsview processes started, confirmed by the same before/after process-count method used throughout this investigation. Signed-off-by: yihou <yihou@amd.com>
wiring measured that HOME=$AGENT_SYS_HOME (already present in the env dict at all three subprocess.run call sites) is a second, stronger gate 3 that nobody designed: AgentsView computes every provider's *default* session root from HOME, so pointing it at the prefix means every root it could scan resolves inside the prefix -- no denylist needed, and unlike OTHER_PROVIDERS this gate cannot go stale when upstream adds a provider we have never heard of. Measured with doctor sync run under exactly this environment: 122 roots listed, 0 outside the prefix. Design doc (da7f5e0) already documents this as gate 5, in words that say the gate exists by accident rather than by contract because no test held it -- a one-line "tidy up the env dict" edit would have silently restored every default root to the user's real home with nothing else here going red. Added the assertion to the existing spy-based test for ensure_running, plus two new tests for check_disabled_agents and discover_providers (the other two call sites). Confirmed each actually catches the regression: mechanically stripped HOME from all three env dicts, watched all three tests go red with the exact KeyError this assertion exists to prevent, restored, confirmed green again -- the same discipline used earlier for _patched_environ and the completeness check. Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
…d the orphan trap Three measurements from PHASE0 that a future maintainer would otherwise have to rediscover: - AGENTSVIEW_NO_DAEMON=1 was tried and rejected. It makes health/projects/ session list refuse outright rather than fall back to a direct SQLite read, even against a populated database -- which in this function's own error handling collapses to a permanently empty result: a check that is a no-op forever and never looks broken. - serve stop / daemon stop only reach the most recently started daemon; an orphan is unreachable by any documented command. - A validation path must never start a daemon: health does, doctor sync does not, and delegating the port choice is the rule this component exists to hold. Signed-off-by: yihou <yihou@amd.com>
Signed-off-by: yihou <yihou@amd.com>
dorado269
requested review from
JohnQinAMD,
jiejingzhangamd,
limou102 and
xiaobochen-amd
as code owners
September 3, 2026 14:47
dorado269
marked this pull request as draft
September 4, 2026 04:00
dorado269
changed the base branch from
dev.yaoc.aiopt.task_package
to
dev.yihou.aiopt.task_package
September 4, 2026 04:02
dorado269
commented
Sep 4, 2026
| @@ -1,107 +1,107 @@ | |||
| # Task — `e2e_deploy_standardized`: the first stage of the LLM e2e optimisation task package | |||
| # Task — wire **AgentsView** into `agent_sys` as its o11y panel | |||
Collaborator
Author
There was a problem hiding this comment.
do not modify this file when submit to git
dorado269
commented
Sep 4, 2026
| via `assignment.environment`; this subprocess is not one and so was never | ||
| covered. It inherited the ambient environment and dropped one JSONL into | ||
| `~/.claude/projects` on every single run — measured during acceptance by | ||
| matching the prompt string above to the file. Small, and still a breach of |
Collaborator
Author
There was a problem hiding this comment.
comments is too looooong, keep every not file level comment in at most 5 lines, better 3 line
dorado269
commented
Sep 4, 2026
|
|
||
| outcome = outs[-1] | ||
| if outcome.level == "ok": | ||
| # **Validated here, at install time, not left for `serve` to discover |
Collaborator
Author
There was a problem hiding this comment.
Answer: brief me what this file does
…d no line
`set -e` is exempt for a non-final command in an `&&` list, so
`[ -n "$expected" ] && [ "$expected" = "$actual" ]` short-circuited and
carried on to install an unverified binary whenever the SHA256SUMS line was
missing -- the one case that test was written for. A real mismatch aborted
correctly the whole time, which is why it read as working.
Split into two statements, and ${tmp:?} in the cleanup trap so a recursive
delete on an empty variable aborts rather than expands.
Three tests run the recipe's install string for real against a stubbed curl:
checksum matching, mismatched, and not found. The first is the positive
control -- without it the other two pass against a recipe that installs
nothing at all.
Signed-off-by: yihou <yihou@amd.com>
…a test
Both the URL and the first-install notice were log.info. Nothing in this
repository configures logging, so the root logger sits at WARNING with no
handler and both lines were discarded -- while the o11y failure paths, being
log.warning, reached stderr through logging.lastResort. The component
reported only its failures. The tests passed because caplog.at_level("INFO")
forces the level from pytest's side, which is a test asserting intent rather
than output.
Both now go through the event stream, which is the thing in this package
whose job is being read. New EventKind O11Y_PANEL, SCHEMA_VERSION 1.3 -> 1.4.
Verified on a real invocation: the line appears on stdout and as
{"kind": "o11y_panel", "url": ...} in --json.
Also the wire nobody tested: deleting the _start_o11y call from main()
outright left the whole tests/cli suite green, so acceptance criterion 2
-- deploying agent_sys starts it -- had no test. Five added, driving main()
for real. And the installer drift guard invented its own skip message when
the branch produced none and then asserted only that it was truthy; it now
drives the real skip branch via a check_cmd that succeeds.
Signed-off-by: yihou <yihou@amd.com>
… file _owns_port read a file of ours holding just a port number, written only by a successful launch and never expired. That is evidence about the past: after our daemon died and the user started their own AgentsView on the same port, both gates passed and the operator was handed a URL to a panel listing every session on their machine, labelled as theirs, with no warning -- the single requirement this component exists to satisfy, failing silently. The witness is now AgentsView's own daemon.<pid>.json, read out of our own AGENTSVIEW_DATA_DIR. A stranger's daemon writes its record into their data directory, so it structurally cannot appear here; the isolation is the filesystem's rather than a convention we maintain. Measured on a real v0.42.0: the record is removed by AgentsView on a clean `serve stop`, so the ordinary case leaves no stale evidence, and the unclean case (SIGKILL, OOM, reboot) is caught by checking the recorded pid for liveness. Read only; AgentsView stays unmodified. Verified against the live resident daemon. This also retires the orphan trap. The port file was written only after the health check passed, so one slow cold start left a live daemon nobody could recognise and the panel was skipped on every subsequent run, permanently, blaming a stranger. AgentsView writes its record when it starts. The two busy-port cases are now reported separately, because their fixes are opposites, and the last unguarded write in the module is gone with the file. Alongside: - resolve_port range-checks; bind answers an out-of-range port with OverflowError, which is not OSError and escaped to the CLI's blanket backstop. 0 is rejected too: it binds, then delegates the port choice to AgentsView's auto-discovery, which this module exists to prevent. - _identifies_as_agentsview catches http.client.HTTPException. Measured: a truncated Content-Length body does *not* reach it (read(amt) returns short), but chunked framing does -- and chunked is what a Go server sends with no length. - write_config writes by rename. A partial read of that file is not a crash, it is disabled_agents coming back short, i.e. every provider re-enabled. - one _binary_env(prefix), where HOME=$AGENT_SYS_HOME was spelled out at three call sites with a test holding each; the named timeout the module was missing; and the Agent-roots parse bounded at the next unindented line. Signed-off-by: yihou <yihou@amd.com>
… no $HOME It did environ["HOME"] and raised KeyError with neither AGENT_SYS_HOME nor $HOME set -- a systemd unit, a stripped cron environment, `env -i`. material.py caught it and warned; prepare.py and cli/environment.py did not. One condition, three behaviours, two of them fatal, on a feature the run never asked for. The line prepare.py replaced could not fail at all. resolve now falls back to $HOME, then the passwd entry, then a per-uid directory in $TMPDIR, and expanduser/resolve the override so `~/foo` and a relative path both mean what they look like -- the cwd moves between zones. test_a_failed_link_does_not_raise reached its warning by deleting $HOME, which was the bug rather than the fixture; it now makes the prefix unreachable through the filesystem, where a real failure would come from. Signed-off-by: yihou <yihou@amd.com>
…ility rules Three things the review changed and the design did not yet say: reuse is gated on AgentsView's own daemon.<pid>.json rather than a port file of ours (with the measurement that it is removed on a clean stop, and why the old witness failed in two directions at once); success goes to the event stream because log.info in this package reaches nobody; and resolving the prefix is not one of the operations allowed to fail. Signed-off-by: yihou <yihou@amd.com>
…dy knew
A run tree was browsable only if you already knew the uuids: `handoffs/<uuid>/`,
`zones/task.<uuid>.<attempt>.<hash>/`. The closure name and the handoff kind
were both in hand at the moment the directory was created, and both thrown
away. They are now the second field:
handoffs/handoff.solutions_a.57882e8c-.../v0/content/
zones/task.main.2c0260e5-.../task.solve_a.310209e3-....0.ce4e41e0/
zones/task.main.2c0260e5-.../validation.solve_a.310209e3-....output_validation.01a143f0/
Two properties keep the label from becoming a contract:
- **Nothing resolves through it.** `find_zone_dir` matches the uuid as a whole
field, and `handoff_dir` finds the directory whose name *is* the uuid or ends
with `.<uuid>`. So a store or zone tree written before labels existed resolves
unchanged, and a renamed closure does not move an artefact.
- **`.` does not survive a label.** The uuid is the last field before the
attempt/version, and `parts[-2]` would read the wrong one otherwise.
The staged copy in a zone takes the store directory's own basename rather than
recomputing the label, which keeps `task_graph`'s kind vocabulary out of
`stage`, `stage_handoffs` and `prepare_validation`.
`handoff.store.version_dir` and `env_mgr.fs.layout.handoff_version_dir` stay the
two sanctioned writers of the shape; `tests/interfaces/test_handoff_layout.py`
pins both, including that either alone would regress the compatibility rule.
The five body-side `examples/*/assets/lib/store.py` readers get the same
scan-then-fallback rule under the same agreement test.
Verified: 2266 passed / 3 skipped / 4 xfailed; `examples/demo2` run end to end
and the tree above read off it; that run's store renamed back to bare uuids and
re-read through all three readers.
Signed-off-by: yihou <yihou@amd.com>
feat(agent_sys): label every runtime directory with the name it alrea…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wires AgentsView into
agent_sysas its o11y panel. AgentsView is used as an unmodified external dependency; every knob turned is one it already publishes.What this gives you
Deploying
agent_sysbrings up a web panel onhttp://127.0.0.1:18888showing only the sessionsagent_sysitself produced. Your own Claude Code is untouched:~/.claudeis never read, written or reconfigured.18888, settable with--agentsview-portorAGENTSVIEW_PORT;--no-agentsviewdisables it.except Exceptionat the call site as a structural backstop.--dry-runor--clean.~/.infera_agent_sys(~/.local-shaped, owned byenv_mgr). Nothing lands in/usr/local/binor~/.local/bin.How the panel is scoped — five gates
CLAUDE_CONFIG_DIRinto the agent child's environment only, neveros.environ.CLAUDE_PROJECTS_DIR→ the prefix, the one root AgentsView scans.disabled_agents— 59 provider names, measured against the real binary.AGENTSVIEW_DATA_DIR; a pre-existing~/.agentsviewis never opened.HOMEredirected into the prefix, so every provider computes its default root inside it. This one is structural: a provider upstream adds next release, absent from gate 3's list, still cannot reach~/.codex. Found by measurement, now held by tests.<zone>/config/projectsis a symlink into the prefix, somaterial.py's per-attempt config dir keeps its credentials while transcripts land somewhere a resident daemon can read.Acceptance
Six checks against pinned commit
7d25923, three arms (control / panel / port-busy), each with a prefix created empty and an ephemeral port. Report:ws.agentsview_o11y/acceptance/PINNED-7d25923/REPORT.md.~/.claude--no-agentsviewCheck 6's original criterion was wrong and is recorded as such rather than quietly rewritten. It compared exit codes of a package whose verdict depends on model output. Across nine demo2 runs there were three failures, always a content validator, on a different arm each round — and in the final round the arm doing the most o11y work exited 0 while the arm doing the least exited 5. The o11y contract itself held exactly: one warning, correct text, zero tracebacks.
Check 3 was confirmed in a real headless browser against the panel arm's own empty prefix — 3 sessions rendered, all
agent_sys's own — not from a JSON body. The panel arm'sbin/was empty at 13:36 and the binary landed at 14:03 from the recipe, so the install path is proven on a machine that had no binary.pytest tests/→ 2227 passed, 3 skipped, 4 xfailed.Notable findings about the dependency
serve --background --port Nignores--portand exits 0 when a daemon already holds that data dir. Fixed with--replace.agentsview healthstarts a background daemon on a port AgentsView picks;doctor syncvalidates identically and starts nothing.AGENTSVIEW_NO_DAEMON=1was tried and rejected — it makeshealthrefuse outright rather than fall back to a direct read.serve stoponly tracks the most recent daemon; orphans are unreachable by any documented command.GET /api/v1/sessionshides one-shot sessions, which is everyagent_sysagent. The web UI callssessions/sidebar-indexwithinclude_one_shot=trueand is unaffected — we spent hours on a non-bug by treating an API response as a proxy for what a person sees.Known limitation
The zone symlink's behaviour under an enforcing policy is untested, because
AGENT_SYS_NO_PERMISSIONS=0currently fails for every AI package atagent/runner.py:1335— a pre-existingagent_sysrefusal, unrelated to this change and confirmed by a paired control arm with one file differing. Read that as untested because currently untestable, never as safe.