release(v4.9.6): opencode 2.x only (Issue #60) - archive the review reports, bump the lockstep version
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
This commit is contained in:
1 parent
0e05b1b677
commit
cb2c84ccd7
29 files changed
+835
-25
No files matched your search
@@ -0,0 +1,43 @@
|
||||
# Review 4709b38f — Issue #60, opencode 2.x
|
||||
|
||||
Reviewed only the snapshot `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261018T055915Z-abe16e/1` (`loop-20261018T055915Z-abe16e`). Head `6b4b96fa1875862ef3bed830fe7b04166b1fad58`, tree `9cfb2106081eba96b58cc6b7573031de0acba399`, base `74333f87d0c02888c2b5b281e912d97e74348c01` is an ancestor. Three commits, 13 files, +460/−275. `git diff --check` is clean. Snapshot porcelain is empty and the snapshot has no `.mam`. Control-plane main is `74333f87d0c02888c2b5b281e912d97e74348c01`, porcelain empty. No product file was edited.
|
||||
|
||||
Host tools: `/usr/bin/python3` 3.9.6, the control-plane venv the same 3.9.6, `/bin/bash` 3.2.57. `bash -n` accepts `create_session.sh`, `resume_session.sh`, `update_yaml_resumed.sh`, `reconcile.sh`, and `status.sh`. `opencode --version` in a temporary home, with `XDG_DATA_HOME`, `XDG_STATE_HOME`, `XDG_CONFIG_HOME`, and `XDG_CACHE_HOME` unset, printed `opencode v2.0.32`.
|
||||
|
||||
The user's background service stayed up for the whole review. Its pid is 86524, the command is `opencode serve --service`, and the service file mtime stayed 1792246838. The real database mtime stayed 1792247140. Nothing in this review called `session delete`, `service stop`, or an API against that database. After the tests the only `opencode` binary still running was that service.
|
||||
|
||||
## What this Mac's database already stores
|
||||
|
||||
A read-only open of `~/.local/share/opencode/opencode.db` shows a migrated database. `session_v2` and `session` each have 4 rows. Every `session_v2` row has `parent_id` NULL, and every id matches `[A-Za-z0-9_]`. The 2.x tables present are `session_v2`, `session_message`, `session_inbox`, `session_pending`, `event`, and `event_sequence`. The 1.x tables a migration keeps are also present: `session`, `message`, `part`, `todo`, and `session_share`. `todo` and `session_share` are keyed by `session_id`. Column names only were read. No row body was printed.
|
||||
|
||||
That matches the adapter. `discover` reads `session_v2` where `parent_id IS NULL` (`opencode.py:220`). A child shares the workspace directory and can be newer than the TUI session, so drift C in `reconcile.sh:966-968` uses the same filter. `verify_artifact` still accepts a known child id (`opencode.py:115`). `status.sh` checks `session_v2` in both copies of `resume_on_disk`.
|
||||
|
||||
## Purge scope
|
||||
|
||||
`purge_artifacts` calls `opencode session delete --standalone -- <id>` only when `session_v2` contains that id (`opencode.py:136-141`). The fake CLI, and the real 2.0.32 contract below, delete that id and its children from the 2.x tables and leave the other session alone. A missing id does not invoke the CLI (`test_purge_does_not_run_opencode_for_a_session_it_does_not_hold`). A missing binary or a non-zero delete writes a `WARN` and leaves the `session_v2` row for `residual_artifacts` (`opencode.py:143-149`, `test_a_failed_delete_is_warned_and_reported`).
|
||||
|
||||
The SQL that follows deletes `message`, `part`, and `session` (and the plural names) for that same id. It does not delete `todo` or `session_share`. `db_rows_naming` reports any remaining `session_id` or `aggregate_id` rows, so a migrated `todo` stays visible: `test_opencode_residual_reports_event_rows` expects residual `[<db> (todo.session_id: 1 rows)]` and eight entries for the other session. `session_share.session_id` is on that same report path. The append of `sqlite rows for session` happens when one of those 1.x tables exists (`opencode.py:172-173`), including when the delete matched no row. A fresh 2.x database has none of those tables, and the real contract asserts the purged list is only the session-delete line.
|
||||
|
||||
## Spawn, resume, and the real binary
|
||||
|
||||
`spawn_spec` is `opencode --auto --standalone`. `resume_spec` with a materialized id is `opencode --session <id> --auto --standalone` (`opencode.py:198-204`). The same strings are the `opencode` arms in `create_session.sh`, `resume_session.sh`, and `update_yaml_resumed.sh`. `test_spawn_and_resume_never_pass_agent_and_run_standalone` reads those three scripts and rejects a line that still contains `--agent`. Live skill files and `docs/` have no `opencode db path` and no `--agent build`. `VERSIONS.md`, `bug-report/`, and `.agents/reports/` still describe the 1.x command; the brief leaves those historical notes in place. `create_session.sh` still treats `auth.json` or a provider key as enough, and otherwise accepts `opencode --version`. That check was left as it was, and `--version` exits 0 on this install.
|
||||
|
||||
`_run` points `HOME` and `XDG_DATA_HOME` at the discovery home before `debug paths` or `session delete` (`opencode.py:80-87`). `_resolve_db` reads the `db` line. The fallback is `<home>/.local/share/opencode/opencode.db`.
|
||||
|
||||
The opt-in contract `test_real_opencode_2x_contract` ran here, because 2.0.32 is installed. It used a pytest temporary home and tmp, unset the four `XDG_*` variables, and called only `--help`, `api --standalone`, and `session delete --standalone`. `--help` contains `--standalone` and `--session`. Discover returned the parent id. `verify_artifact` on the child was true. Purge of the parent cleared parent and child residuals. A second delete exited 1 with `Session not found`. No model prompt was sent.
|
||||
|
||||
This review did not start a herdr pane, so it did not drive create, a first TUI message, drift C, stop, and resume as one live chain. The pieces of that chain are the command lines above, drift C's `session_v2` query, and `verify_session_uuid`, which calls the adapter. Stop's graceful `/exit` then kill-session then SIGKILL path is unchanged. `--standalone` is what makes the server a child of that TUI. The id charset on this database has no shell metacharacters, so the unquoted `$UUID` in `resume_session.sh` is safe for the ids stored here.
|
||||
|
||||
The new code uses `HOME`, `XDG_DATA_HOME`, sqlite, and `subprocess`. Nothing in it is macOS-only. This host is macOS, so Linux was not executed here.
|
||||
|
||||
## Tests
|
||||
|
||||
Pytest used the control-plane venv, `PYTHONDONTWRITEBYTECODE=1`, `-p no:cacheprovider`, and `--basetemp` `/tmp/mam4709-4709b38f-pybase`. Inherited `HERDR_*`, `MAM_*`, `MQTT_*`, `SKS_*`, `WORKSPACE_ROOT`, `DELEGATE_JOB_LOGS_DIR`, `HOME_DIR`, `CLAUDE_PROJECT_DIR`, `CLAUDE_CONFIG_DIR`, `CLAUDE_CODE_TMPDIR`, `CODEX_HOME`, and `PYTHONPATH` were dropped.
|
||||
|
||||
On the snapshot, 44 tests passed in 7.56 s: `tests/test_issue60_opencode_v2.py` (including the real-binary contract), `tests/test_a4_adapter_contract.py`, and `tests/test_issue31_purge_residual.py::test_opencode_residual_reports_event_rows`. No skip and no error.
|
||||
|
||||
A separate clone whose `discover` query read `session` instead of `session_v2` failed both `test_discover_and_verify_read_session_v2_and_skip_child_sessions` and `test_a_fresh_2x_database_has_no_session_table_and_still_works` (`assert [] == ['ses_main']`), in 1.07 s. A fresh 2.x database has no `session` table, the query raises, and `discover` returns `[]`. The clone was discarded. Snapshot porcelain stayed empty.
|
||||
|
||||
After the report, snapshot porcelain is still empty, the snapshot still has no `.mam`, and control-plane porcelain is still empty at `74333f87`. The herdr config mtime is still 1784456394. The opencode database mtime is still 1792247140 and service pid 86524 is still `opencode serve --service`.
|
||||
|
||||
[VERDICT: PASS]
|
||||
@@ -0,0 +1,53 @@
|
||||
# Review 5ab36507 — Issue #60, second pass
|
||||
|
||||
Reviewed only the snapshot `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261018T064723Z-79133f/1` (`loop-20261018T064723Z-79133f`). Head `cb5f439cce41a2741a6b9974a308a765e50f00ad`, tree `cfec95403cbde10a6340b9007e1246c83be461cd`, base `74333f87d0c02888c2b5b281e912d97e74348c01` is an ancestor. Four commits, 14 files, +689/−300. `git diff --check` is clean. Snapshot porcelain is empty and the snapshot has no `.mam`. Control-plane main is `74333f87d0c02888c2b5b281e912d97e74348c01`, porcelain empty. No product file was edited.
|
||||
|
||||
The new commit on top of the first-pass head `6b4b96f` is `cb5f439` (`fix(opencode): a purge takes its child sessions' 1.x rows, the background service alone holds no session, XDG_DATA_HOME is followed`). The checks below are against the whole base..head range.
|
||||
|
||||
Host tools: `/usr/bin/python3` 3.9.6, the control-plane venv the same 3.9.6, `/bin/bash` 3.2.57. `bash -n` accepts `create_session.sh`, `resume_session.sh`, `update_yaml_resumed.sh`, `reconcile.sh`, and `status.sh`. `opencode --version` in a temporary home, with `XDG_DATA_HOME`, `XDG_STATE_HOME`, `XDG_CONFIG_HOME`, and `XDG_CACHE_HOME` unset, printed `opencode v2.0.32`.
|
||||
|
||||
The user's background service stayed up for the whole review. Its pid is 86524, the command is `opencode serve --service`, and both service-file mtimes stayed 1792246838. The real database mtime stayed 1792247140, and a read-only count stayed at 4 `session` rows and 4 `session_v2` rows. `lsof` on that database shows only pid 86524, and that command line contains `serve --service`. Nothing in this review called `session delete`, `service stop`, or an API against that database.
|
||||
|
||||
## What cb5f439 changes
|
||||
|
||||
`purge_artifacts` records descendants before `opencode session delete` (`opencode.py:162`). `_descendants` walks `parent_id` in `session_v2` and, when that column exists, in the 1.x `session` table, at every depth, through a read-only URI (`opencode.py:195-217`). The SQL that follows deletes `message`, `part`, `todo`, `session_share`, and `session` (and the plural names) for the parent and those descendants (`opencode.py:178-190`). `todo` and `session_share` are keyed by `session_id` on this machine's migrated database; the purge deletes those rows and the report path is what remains. A fresh 2.x database has none of those tables, and the real contract still expects the purged list to be only the session-delete line.
|
||||
|
||||
`residual_artifacts` asks `db_rows_naming` for the parent and for each descendant still on record, and suffixes the descendant lines with `[child session <id>]` (`opencode.py:229-237`). `test_purge_takes_the_1x_rows_of_the_child_sessions_too` seeds a parent, a child, a grandchild, and an unrelated session, and expects the unrelated session to keep six entries. `test_a_failed_delete_reports_the_child_sessions_left` expects the child `session_v2` row, with that suffix, when the binary is missing.
|
||||
|
||||
`conversation_in_use` still treats a command line that names the id as in use. A process that holds the shared database counts as well, except a command line that contains `serve --service` (`opencode.py:240-262`). On this Mac that is the only holder of the real database, so a purge of a session in that file is not refused solely because the user's service is running. Any other holder still returns true, and the purge CLI still exits 4 before it deletes (`agents/__main__.py:146-148`). `lsof` or `ps` raising is treated as in use. When `lsof` is absent the database-holder check returns false; the command-line check still runs. This host has `lsof`.
|
||||
|
||||
`_data_home` returns the caller's `XDG_DATA_HOME` when that variable is set and `ctx.home_dir` is the caller's own home (realpath), and `<home>/.local/share` for any other home (`opencode.py:87-94`). `_run` puts that value in the child environment (`opencode.py:103-106`). `test_the_data_dir_follows_the_callers_xdg_data_home_only_for_its_own_home` covers both sides and the unset case.
|
||||
|
||||
`resident_children` is `('opencode',)` (`opencode.py:70-73`). `background_children` records a process's children before it skips a resident name (`stall_watch.py:126-132`), so the `opencode serve --stdio` child is idle and a tool under that child still counts. `test_the_standalone_server_is_a_resident_child_but_its_tools_are_work` passed here. The Linux `_proc_table` reads `/proc`; the name check also uses `argv[0]`, so a process whose comm is the binary and whose argv0 is `opencode` still matches. This host took the `ps` path.
|
||||
|
||||
The real-binary test binds `_bin` to the absolute path it already resolved (`test_issue60_opencode_v2.py` `test_real_opencode_2x_contract`), so the later calls do not depend on `PATH` under the temporary home. Drift C in `reconcile.sh:966-968` keeps `parent_id IS NULL`. `test_comp_opencode_create_and_reconcile_and_stop` inserts a newer child in the same directory and requires the pinned id to be the parent. That test passed.
|
||||
|
||||
## Tests that catch a revert
|
||||
|
||||
On the snapshot, 50 tests passed in 65.40 s: `tests/test_issue60_opencode_v2.py` (including the real-binary contract), `tests/test_a4_adapter_contract.py`, `tests/test_issue31_purge_residual.py::test_opencode_purge_leaves_no_rows`, and `tests/test_tier2_component.py::test_comp_opencode_create_and_reconcile_and_stop`. No skip and no error. Pytest used the control-plane venv, `PYTHONDONTWRITEBYTECODE=1`, `-p no:cacheprovider`, and `--basetemp` `/tmp/mam5ab3-5ab36507-pybase`. Inherited `HERDR_*`, `MAM_*`, `MQTT_*`, `SKS_*`, `WORKSPACE_ROOT`, `DELEGATE_JOB_LOGS_DIR`, `HOME_DIR`, `CLAUDE_PROJECT_DIR`, `CLAUDE_CONFIG_DIR`, `CLAUDE_CODE_TMPDIR`, `CODEX_HOME`, `PYTHONPATH`, and the four `XDG_*` variables were dropped.
|
||||
|
||||
A separate clone, discarded afterward, failed three probes:
|
||||
|
||||
- SQL limited to the parent id: `test_purge_takes_the_1x_rows_of_the_child_sessions_too` failed in 0.66 s. The purged list was only the session-delete line.
|
||||
- Every database holder treated as in use: `test_the_background_service_alone_does_not_hold_a_session` failed in 0.96 s (`True` where the service-shaped holder must leave the session free).
|
||||
- Drift C without `parent_id IS NULL`: `test_comp_opencode_create_and_reconcile_and_stop` failed in 17.08 s. `opencode_session_id_own` stayed unset, so the parent was not pinned.
|
||||
|
||||
Snapshot porcelain stayed empty.
|
||||
|
||||
The real contract ran under a pytest temporary home and tmp, with the four `XDG_*` variables unset, and called `--help`, `api --standalone`, and `session delete --standalone`. `--help` contains `--standalone` and `--session`. Discover returned the parent. `verify_artifact` on the child was true. Purge cleared parent and child residuals. A second delete exited 1 with `Session not found`. No model prompt was sent. After that run the real database still had 4 and 4 rows.
|
||||
|
||||
## Boundaries
|
||||
|
||||
`status.sh` `resume_on_disk` queries `session_v2` once it has opened a database (`status.sh:127` and the second copy at `:337`). The path it opens is still `$home/.local/share/opencode` (then `storage.db`, then a `project/*.db` walk). Drift C asks the adapter, which follows `XDG_DATA_HOME` for the caller's own home. On this host `XDG_DATA_HOME` is unset, so both look at `~/.local/share/opencode/opencode.db`. A caller who sets `XDG_DATA_HOME` would see drift C and `resume_on_disk` use different files.
|
||||
|
||||
The append of `sqlite rows for session` happens when one of the 1.x tables exists (`opencode.py:188-190`), including when the delete matched no row. `_run` copies the rest of the environment and sets `HOME`, `HOME_DIR`, and `XDG_DATA_HOME`. The contract test clears `XDG_STATE_HOME`, `XDG_CONFIG_HOME`, and `XDG_CACHE_HOME` before it starts the binary.
|
||||
|
||||
This review did not start a herdr pane, so it did not drive create, a first TUI message, drift C, stop, and resume as one live chain against a real TUI. The tier-2 test drives create, drift C, and stop against the mock herdr and the fake CLI, in a sandbox home. Stop's graceful `/exit` then kill-session then SIGKILL path is unchanged. `--standalone` is what makes the server a child of that TUI. The id charset on this database matches `[A-Za-z0-9_]`, so the unquoted `$UUID` in `resume_session.sh` is safe for the ids stored here.
|
||||
|
||||
Live skill files and `docs/` have no `opencode db path` and no `--agent build`. `VERSIONS.md`, `bug-report/`, and `.agents/reports/` still describe the 1.x command; the brief leaves those historical notes in place. `create_session.sh` still treats `auth.json` or a provider key as enough, and otherwise accepts `opencode --version`. That check was left as it was, and `--version` exits 0 on this install.
|
||||
|
||||
The new code uses `HOME`, `XDG_DATA_HOME`, sqlite, `subprocess`, `lsof`, and `ps`. `stall_watch` reads `/proc` when that directory exists. Nothing in the new adapter code is macOS-only. This host is macOS, so Linux was not executed here.
|
||||
|
||||
After the report, snapshot porcelain is still empty, the snapshot still has no `.mam`, and control-plane porcelain is still empty at `74333f87`. The herdr config mtime is still 1784456394. The opencode database mtime is still 1792247140 and service pid 86524 is still `opencode serve --service`.
|
||||
|
||||
[VERDICT: PASS]
|
||||
@@ -0,0 +1,37 @@
|
||||
# Review d384cdc0 — Issue #60, third pass
|
||||
|
||||
Reviewed only the snapshot `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261018T073639Z-b5cb7f/1` (`loop-20261018T073639Z-b5cb7f`). Head `0e05b1b6777ceb837066454ac688e04a0f5d14a0`, tree `c5cb1b16af283b3fdb447bafb865ba1abbfbb5a8`, base `74333f87d0c02888c2b5b281e912d97e74348c01` is an ancestor. Five commits, 15 files, +705/−330. `git diff --check` is clean. Snapshot porcelain is empty and the snapshot has no `.mam`. Control-plane main is `74333f87d0c02888c2b5b281e912d97e74348c01`, porcelain empty. No product file was edited.
|
||||
|
||||
The new commit on top of `cb5f439` is `0e05b1b`. It changes three files: `tests/_agent_home_guard.py`, `.agents/skills/multi-agent-mux-status/scripts/status.sh` (both copies of `resume_on_disk`), and the `--version` probe in `tests/test_issue60_opencode_v2.py`.
|
||||
|
||||
Host tools: the control-plane venv is Python 3.9.6, `/bin/bash` is 3.2.57. `bash -n` accepts `status.sh` and `create_session.sh`. `opencode --version` in a temporary home, with an environment of only `PATH`, `HOME`, and `TMPDIR`, printed `opencode v2.0.32`.
|
||||
|
||||
The user's background service stayed up. Its pid is 86524, the command is `opencode serve --service`, and both service-file mtimes stayed 1792246838. The real database mtime stayed 1792247140, with 4 `session` rows and 4 `session_v2` rows. The real `opencode.log` mtime stayed 1792308195 and its size stayed the same. The herdr config mtime stayed 1784456394.
|
||||
|
||||
## What 0e05b1b fixes
|
||||
|
||||
`_agent_home_guard.DROPPED_VARS` now includes `XDG_DATA_HOME` (`_agent_home_guard.py:21`). `conftest._isolate_agent_homes` drops that tuple for every test, and `pytest_configure` records the value first so the session guard can watch it. `watch_dirs` uses `<XDG_DATA_HOME>/opencode` when the recorded environment has the variable, and `<home>/.local/share/opencode` otherwise (`_agent_home_guard.py:48-49`).
|
||||
|
||||
That matches the second-pass failure. The adapter follows the caller's `XDG_DATA_HOME` when `ctx.home_dir` is the caller's own home. A sandbox that only changed `HOME` still inherited the runner's `XDG_DATA_HOME`, so discovery and purge resolved the runner's data directory. Dropping the variable makes `HOME` govern, which is what `_data_home` does when the variable is unset.
|
||||
|
||||
`test_l1_every_path_variable_the_code_reads_is_accounted_for` scans adapters for `*_HOME` reads. `XDG_DATA_HOME` is one of them (`opencode.py` `os.environ.get("XDG_DATA_HOME")`). A clone whose `DROPPED_VARS` omitted it failed that test in 0.04 s with `['XDG_DATA_HOME']`. The suite below was started with `XDG_DATA_HOME` pointed at an empty directory `/tmp/mamd384-d384cdc0-xdg`. After 65 passed tests that directory was still empty.
|
||||
|
||||
`status.sh` `resume_on_disk`, in the `--json` block and in the text block, asks `get_adapter('opencode')._resolve_db(DiscoveryContext(..., home_dir=home))` (`status.sh:108-111` and `:305-308` in the second copy). `home` is `HOME_DIR`. `env_python` passes the parent environment through, so a set `XDG_DATA_HOME` reaches `_data_home` when `HOME_DIR` is the caller's home. A copy of the tree, with the fake opencode on `PATH` and the only database under a separate `XDG_DATA_HOME`, returned exit 0. `--json` `resume_state` was `yes` for `ses_probe` and `MISSING` for an id the database does not hold. Text mode exited 0 and the session's line contained `yes`. `~/.local/share/opencode/opencode.db` under that sandbox home was not created. The existing status checks in the same suite (`test_status_json_schema_fields`, `test_status_text_headers_presence`, and the claude and agy `resume_on_disk` helpers) also exited 0.
|
||||
|
||||
`_real_opencode` runs `--version` inside `tempfile.TemporaryDirectory` with `HOME` and `TMPDIR` set to that directory and no `XDG_*` variables (`test_issue60_opencode_v2.py:298-300`). The same shape, run on its own, wrote a log only under that temporary home. The real log was unchanged. The opt-in contract ran as part of the 65 (no skip).
|
||||
|
||||
## Suite
|
||||
|
||||
Pytest used the control-plane venv, `PYTHONDONTWRITEBYTECODE=1`, `-p no:cacheprovider`, and `--basetemp` `/tmp/mamd384-d384cdc0-pybase`. Inherited `HERDR_*`, `MAM_*`, `MQTT_*`, `SKS_*`, `WORKSPACE_ROOT`, `DELEGATE_JOB_LOGS_DIR`, `HOME_DIR`, `CLAUDE_*`, `CODEX_HOME`, and `PYTHONPATH` were dropped. `XDG_DATA_HOME` was the empty sentinel above. `XDG_STATE_HOME`, `XDG_CONFIG_HOME`, and `XDG_CACHE_HOME` were unset.
|
||||
|
||||
65 passed in 68.75 s: `tests/test_issue55_agent_homes.py`, `tests/test_issue60_opencode_v2.py` (including the real-binary contract), `tests/test_a4_adapter_contract.py`, `tests/test_issue31_purge_residual.py::test_opencode_purge_leaves_no_rows`, `tests/test_tier2_component.py::test_comp_opencode_create_and_reconcile_and_stop`, and the four status cases named above. No skip and no error. Snapshot porcelain stayed empty.
|
||||
|
||||
`opencode debug paths` in a temporary home prints the `db` line under that home's `.local/share/opencode` and creates `log/opencode.log` there. It does not create `opencode.db`. So an opencode row in `status.sh` now runs that command, and a real status check appends the log under the data directory `_resolve_db` is about to open. The RESUME value and the exit code measured above stay 0 / `yes` / `MISSING`. The database file is untouched by the path lookup.
|
||||
|
||||
The earlier commits are unchanged in this pass: purge still collects descendants before `session delete` and deletes the 1.x rows of parent and children, `conversation_in_use` still ignores only a `serve --service` holder, drift C still requires `parent_id IS NULL`, and spawn/resume stay `--auto --standalone`. The tier-2 test in this suite pins the parent when a newer child shares the directory, against the mock herdr. This review did not drive a live herdr pane through create, a first TUI message, stop, and resume.
|
||||
|
||||
The new code uses the environment, sqlite, and `subprocess`. Nothing added in `0e05b1b` is macOS-only. This host is macOS, so Linux was not executed here.
|
||||
|
||||
After the report, snapshot porcelain is still empty, the snapshot still has no `.mam`, and control-plane porcelain is still empty at `74333f87`. The herdr config mtime is still 1784456394. The opencode database mtime is still 1792247140, the opencode log mtime is still 1792308195, and service pid 86524 is still `opencode serve --service`.
|
||||
|
||||
[VERDICT: PASS]
|
||||
Reference in new issue
Block a user