Skip to content

Commit e957737

Browse files
authored
feat(cli)!: one --refresh[=live|machine] flag for status, system and maintain (ADR-0063) (#263)
* docs(plan): add test temp-folder cleanup research to Branch 9 * docs(plan): Branch 6b code-level plan (one refresh flag) * docs(plan): split Branch 6b into CLI (6b) and dashboard (6c); no legacy spellings * fix(limits): ask Codex for its quota only when Codex is found readLimits gates the app-server spawn on providers.mjs's new recordedHostPresence('codex'), reading the host-setup evidence detectHosts already records for every host on each /api/status poll instead of probing. Absent, stale (>6h) or PATH-invalidated evidence reads as 'unconfirmed', never 'not-found'; either non-'found' outcome serves the last cached figure (if any) and skips the spawn, and the Limits panel now names both new reasons instead of falling back to its generic sentence. * fix(limits): say "not refreshed" when Codex's quota was deliberately not requested codexFailedShort prefixed every Codex unavailable reason with "last refresh failed", which is false for host-not-found/host-unconfirmed: B6b-D1's presence gate skips the app-server spawn entirely for those, so no refresh was ever attempted. Those two reasons now render "not refreshed" instead, alongside every other reason keeping "last refresh failed" unchanged. Also matches the two new CODEX_WHY strings' apostrophes (&rsquo;) to their neighbours. * feat(refresh): one --refresh flag with live and machine strengths, starting with ak status src/lib/refresh.mjs holds the shared refresh operation (ADR-0063): the strengths (a bare --refresh, =live, =machine), one ordered stage table, the stage runner, the CLI stage set over one lazily built collector, Maintenance service and management facade, and the stage renderer. The bin rewrites a bare --refresh to --refresh= before parseArgs for commands whose refresh option takes a value. ak status takes the flag. --deep and --live are gone and get the parser's generic unknown-option error. --refresh=live runs the same live checks the old --live ran, then re-checks local evidence so the rows show them. With --json, every human line goes to stderr while the stages run and stdout carries one JSON object with a refresh summary. A failed stage exits 1. The stale-result hint on remembered live checks now names ak status --refresh=live. humanOutputToStderr moves from sync.mjs to output.mjs unchanged. * fix(refresh): truthful --json help, a live-stage start line, and refusals for stray arguments and half-injected services The status help said a refresh under --json sends its stage lines to stderr; no stage lines print there at all, only what a stage itself writes. The live stage now announces its start with a dim line, since the checks can run for a minute with nothing else on screen. A refresh with a positional (ak status --refresh live) is a usage error naming the one-token spelling instead of silently running the bare strength. cliRefreshStages refuses a Maintenance service or facade injected without the other, because the half it would build uses the default control root. A test pins that the machine stages' ticker stays off stdout under --json. * feat(refresh): ak system and ak maintain take the same --refresh flag * docs(plan): fold the drift() failed-fetch fix into Task 9; group 6a leftovers in Branch 9 * refactor(verify): fold ak x verify into ak status --refresh=live The live checks and slow proofs move to src/lib/live-checks.mjs. --only names checks for --refresh=live and decides the exit code; without it the quick checks that apply run (mcp whenever Codex is enabled) and a failure stays a warning. Slow proofs (learning, harvest, aqe, memory-routes) run only when named. Results are remembered as status-refresh-live; records from the earlier sources read as an earlier live check. ak x verify is gone and gets the generic unknown plumbing command error. The nightly deep proofs call the new spelling. * fix(status): with --only, only the named checks decide the exit code Rows and failed refresh stages still print and reach --json, but with --only the exit code is 1 only when a named check failed, was inconclusive or did not run. ak system refuses --only: it reports no live checks. The live-check evidence store takes its id list from the refresh vocabulary, and a named check that does not apply says on its line that its result is not remembered. * feat(host): consent-gated connection check from the CLI * fix(host): check-connection always answers --json with one JSON object * refactor(cli): rename operations that are not refreshes * fix(security-check): scan the project folder and say so * fix(sync): --skip versions also skips the online version lookup `ak sync --skip versions` (and `--skip self`, `--skip ruvnet-brain`) still made the forced pre-plan lookup for that part, and the plan read fetched again whenever the 24 h cache had expired. A skipped part is now never looked up: the plan read and the converge proof get what kit.json recorded for it, through a new `versionEvidence` on status's collect() context. The plan-time lookups move out of sync.mjs into src/commands/sync/plan-versions.mjs: refreshPlanVersions makes the forced lookups for every part --skip does not name and returns cache-only evidence for the parts it does; skippedVersionEvidence is recomputed for the converge proof, so installed versions are read after the apply phase. The health snapshot reads the same cache-only drift when versions is skipped. A sync that skips nothing behaves as before (ADR-0063). versions.mjs gains cachedOnlyLatest, a fetchLatest that never touches the network. ruvnet-brain.mjs drift() gains cacheOnly, which reports the recorded release with no lookup and no write; its cached read and its lookup become two small helpers. converge takes an injectable brainDrift for tests. * fix(sync): --dry-run previews the online version lookup without recording it A dry run now makes the lookups a real sync makes before it plans (npm versions for ruflo, agentic-qe and npm-managed hosts, the kit's own tags, Ruflo's release dates, the Brain release while ak manages it) and records nothing: driftReport, selfDrift and the Brain drift take record: false, and the release dates land in a copy of kit.json. The results reach the plan read through versionEvidence. Every npm view in the preview runs with its npm cache in a per-run folder under the OS temp directory (logs off, update notifier off), removed once the lookups are done, so ~/.npm is untouched. When every lookup fails, the dry run prints one line saying versions were not checked online and the plan uses the recorded ones. A registered ruvector is read the way a real sync's plan read does, looked up once its cache has expired, again without recording. --dry-run --no-upgrade makes no lookup and reads every part from the cache. Before this change, a dry run on an expired cache wrote kit.json and ~/.npm. A failed lookup never erases a good one: when the Brain's GitHub release or ruvector's npm lookup answers nothing, the recorded latest (and the Brain's asset fact) stays, last is not restamped so the next call retries, and the drift reports it as a cache fallback. This holds on every path, including ak status --refresh. Each Brain drift helper now returns its own source. --skip ruvector leaves ruvector's lookup out, like versions, self and ruvnet-brain: both sync reads get the recorded ruvector drift. The skip tests now answer newer versions for the skipped part, so a leaked lookup changes that part's kit.json record and fails the byte comparison. * fix(versions): a failed lookup keeps the cached version and waits one TTL window before retrying When the Brain's GitHub release or ruvector's npm lookup answers nothing, the recorded latest (and the Brain's asset fact, install record and held refresh) stays in kit.json and is reported as a cache fallback, and last is restamped. An offline ak status or dashboard poll therefore waits on these lookups once per TTL window instead of on every read, and ak status --refresh still forces a retry. A new observedAt field keeps when the recorded latest was actually seen, carried forward across failures, so the Brain row's observation label never names the failed attempt. record: false and cacheOnly still write nothing. The dry-run preview makes its temporary npm cache folder only when an npm lookup runs, and a failed removal of that folder no longer fails the preview. Its offline line gives the age of the parts it could not check, or the oldest of them when they differ. The sync command tests' dry runs now answer every version lookup themselves, so a machine with npm in /usr/bin never queries the real registry from the suite. * docs(plan): fold 6c into 6b, merge Branches 7 and 8, trim Branch 9 (maintainer restructure) * refactor(maintain): remove recipe refresh until a registry exists No registry is configured for any installation, so ak maintain recipes refresh, the ADR-0048 v2 route, the facade method, and the recipeRegistry/fetchImpl service options that existed only for it can never succeed. Remove every user-reachable path; the recipe store's verified-staging function (allowlist/HTTPS/redirect/signature checks, maintenance/management/recipes.mjs) and its own tests stay as the library a future registry calls. The retired recipes refresh subverb gets the parser's generic unknown-subverb error, and the retired v2 route answers 405 exactly like any other unknown method or route. * fix(maintain): refuse --only and --project-trees without --refresh; never build a default service beside injected stages * fix(versions): a total lookup failure keeps the cached versions and waits one TTL window driftReport and selfDrift now follow the rule the Brain and ruvector lookups already use. When every npm lookup fails, the recorded versions (seen, and the kit's best candidate) stay in kit.json and last is restamped, so an offline ak status, dashboard poll or drift nudge waits on the registry once per TTL window instead of on every read. force (a real ak sync, ak status --refresh) still retries. observedAt keeps when the recorded versions were actually seen (per package for driftReport, and now for selfDrift too), taken from the previous last for a record written before it existed, so the dry-run offline line still gives the age of the recorded versions. A partial kit lookup whose cached candidate still wins renews nothing, as before. record: false never writes. The reads for a part --skip names now pass cacheOnly (no lookup, no write) instead of a lookup that always fails, which the new rule would otherwise have restamped; cachedOnlyLatest is removed. Two tests that read kit.json after a failed forced lookup now compare only what they meant to: the versions part of the record, and the config the live checks saw. * fix(sync): a host probe that fails before planning is reported and the sync goes on Before it reads the plan, a real ak sync re-checks each enabled host and the shared host setup. A probe that threw used to end the whole sync. Each host's probe and the host-setup probe are now guarded: a warning names the host (or host setup) and the error, and the plan reads that host as ak last recorded it. kit.json itself is still read unguarded, so an unreadable config keeps its own error and recovery text. * test(sync): the real sync tests answer every version lookup themselves The non-dry sync tests inside withOpencodeCli put /usr/bin on PATH, so on a machine with /usr/bin/npm their forced version lookups would have queried the real npm registry. realSync now injects offline lookups, as the dry-run helper already did, and so does the child-process helper the --json tests use. * fix(cli): --json failures stay JSON and keep their recovery text; --skip lines print once A --json invocation now always gets exactly one JSON object on stdout, with every human line (the message, the help, the recovery commands) on stderr. - An option the parser rejects answers { error, exitCode: 2 }; ak sync answers its own empty result shape with error (jsonUsageError). A retired spelling gets the parser's generic unknown-option text, with no hint. - The usage errors ak status, ak system and ak maintain raise themselves (a bad --refresh value, a stray strength argument, --only or --project-trees misuse, an unknown maintain verb) answer { error, exitCode: 2 }, each through its command's one usage-error path. - An unreadable kit.json answers { error, exitCode: 1, recovery } from the bin, and ak sync --json adds recovery to its result. configErrorRecovery in config.mjs builds the same mv or Move-Item commands the human output prints. Without --json the output is unchanged. ak sync no longer repeats a skipped item's "skipped by request" line in the verdict when the plan announcement already printed it; the JSON skipped list is unchanged. The help for sync, status, system and maintain, and the sync --json notes in UPGRADING and INSTALLATION, describe the JSON failure answers. * fix(versions): no false "recorded just now", no offline rewrite loop A failed lookup restamps last even when nothing was ever recorded, so the dry-run offline line fell back to that last and said "this plan uses the versions ak recorded just now" (or "2d ago" for an expired ruvector record) where it should say ak has recorded none. Each part's last now stands for an observation only when its record holds a latest: seen entries, the kit's best, the Brain's or ruvector's latest. A stable install whose recorded kit candidate came from the next channel can never use it, so its record is never fresh and every offline lookup restamped and rewrote kit.json. That failure now writes nothing, as before the restamp rule. Dropping the candidate instead would make an empty record look fresh and stop the lookup for a TTL window once the registry is back, so ak status could not show a real latest. * fix(cli): config errors keep their recovery under maintain --json; --json after -- is positional ak maintain's catch-all turned every thrown error into a usage refusal, so an unreadable kit.json under a verb that reads it (discovery, sources add) answered { error, exitCode: 2 } with no recovery. A config error now reaches the CLI's fatal handler: { error, exitCode: 1, recovery } under --json, the recovery commands otherwise, as for every other command. A rejected option answered in JSON when --json appeared only after the -- terminator, where it is a positional. Only the tokens before -- now decide. * fix(cli): honor ak host --dry-run; the bare ak hint counts rows without a fix * fix(cli): maintain --only usage error names ak maintain report, not ak status * docs(plan): close Branch 6b CLI-only; the dashboard half moves to the next program * docs: align help, README and docs with the CLI refresh vocabulary Add tests/kit/refresh-vocabulary-guard.test.mjs (R16-R18) to guard the CLI vocabulary and rewrite every retired spelling it finds (ak x verify, ak status --live/--deep, ak system --deep, ak maintain scan, --refresh-inventory, ak host refresh, ak usage prompts --deep, ak maintain recipes refresh) to its current CLI spelling across README, docs/, claude/ and src/ comments, with no old -> new tables. Dashboard docs keep today's control names and state the new CLI equivalents beside them, as this branch closes CLI-only. Corrects two stale DASHBOARD.md claims (Maintenance does reload on the shared poll; the quoted re-measure status text does not exist) and documents the two new "not refreshed" Codex reasons. Replaces the ledger-only B6b-D1 / Branch 6b Task 1 labels in source/test comments with ADR-0010, and drops the dangling (R17) suffix from three test assertion messages. * docs: state recipe refresh and live-check source facts without history narration Recipe trust and the live-check evidence glossary row named what used to exist instead of only the current state (R17); AQE-EMBEDDINGS.md named the wrong live check for the unmanaged-backend note (the full aqe proof, not aqe-embedding); the troubleshooting "run everything" example named memory redundantly alongside memory-routes, which already covers it. * fix(host): clean up dry-run test fixtures on failure and disclose what pick --dry-run previews * docs: describe the memory and memory-routes checks exactly, and catch retired verbs in listed alternatives * docs: name the memory check by id where it describes the quick round trip * docs(adr): record the CLI refresh vocabulary Branch 6b delivered (ADR-0063) * docs(adr): tighten the --only exit-code wording in ADR-0063 to match namedCheckFailed * fix(maintain): refuse --only for every verb; share one refresh collector ak maintain --refresh=live --only <check> accepted the flag and ran the live checks, but always exited 0 regardless of a failed named check: unlike ak status, ak maintain never renders live-check results or reports their verdict, so the flag was silently accepted and then ignored (final review I-1). --only is now refused with exit 2 for every verb, including the default report, mirroring ak system's own refusal. refreshedReport also built two unrelated collector instances for one --refresh: defaultStages built its own for the machine/inventory stages and the management facade, while createMaintenanceService() (no args) built a second, cold one for the maintenance stage and the later service.report() read (m-2). The collector is now built once in refreshedReport and threaded through both. renderReport printed only the scan-required finding's generic label ("Run Maintenance scan") on an unmeasured machine, naming no command — a new user's first hint invited the retired ak maintain scan verb. It now also prints the finding's own nextAction.steps[0], the exact refresh command (m-3). * fix(cli): skip the drift nudge after a run-level usage refusal The post-command drift nudge ran driftReport() (which shells npm view) whenever mod.run() returned, without checking its exit code. A run-level usage refusal a command raises itself — e.g. a rejected ak status --refresh=bogus — reached the nudge exactly like a successful run and spent a network call a parse error never did (final review m-1). The nudge (and the local-artifact-drift check beside it) is now also skipped when the command's own exit code is 2. * fix(system): describe what a bare/live refresh actually does in --help ak system --help said a bare --refresh (or --refresh=live) "refreshes Maintenance evidence and the inventory, then reprints this same snapshot", omitting that it also re-checks local status (including the online version lookups) and that =live additionally runs the live checks (final review m-6). * test(refresh-vocabulary-guard): catch retired flags behind bracketed options The guard's adjacency regexes required a retired flag directly after the command word, so a bracketed usage line (system [--deep] [--json], status [--json] [--live]) and ak usage prompts --deep behind unrelated prose slipped through undetected — exactly how four current-state docs kept the retired spellings past the original guard (final review I-2). Two new patterns tolerate intervening single-line bracketed options for status/system, and scan the whole line for prompts ... --deep. Also drops the ledger/plan task label from the file header in favor of an ADR-0063 reference (final review m-8). * docs: fix four current-state docs still showing retired spellings machine-footprint.md and ubiquitous-language.md still showed ak system [--deep] [--json]; ubiquitous-language.md also claimed ak system and ak about are "both read-only twins" of their dashboard areas, which is no longer true of ak system --refresh. USAGE-SCORECARD-METRICS.md and prompt-telemetry.md still named --deep as ak usage prompts's text-bearing flag; the current flag is --show-text (final review I-2). * docs(adr): ak status never reads Codex quota; replace ledger-only ids ADR-0010 and ADR-0063 said /api/limits and ak status both go through readLimits to ask codex app-server for its quota. readLimits has exactly one caller, dashboard-server.mjs's /api/limits handler; no status section imports quota.mjs. Both ADRs now say /api/limits only (final review I-3). Both ADRs also cited ledger-only ids (B6b-D1, B6b-D3, M-11) that live only in the gitignored SDD ledger. They now point at the committed branch 6b plan's named rulings (R9, R17) or its "Closing this branch" section instead (final review I-3). Also, ADR-0063's --only bullet read as spanning all three refresh commands; it now says --only is ak status's alone, and that ak system/ak maintain both refuse it outright (paired with the ak maintain code fix). Three precision nits from final review m-5: setup.mjs's collectIntegrationFacts call passes no cwd; selfRecord restamps on a total failure with no cached candidate at all (only a partial answer, or an unusable cached candidate, saves nothing); and ak sync --dry-run's online lookups redirect to, and clean up, a temporary npm cache under the OS temp folder rather than writing "nothing at all". * docs: add check-connection to the host verb row in README README.md's compact command table listed ak host status|pick|reset-routes|off, omitting check-connection even though the usage block and ak --help --all both list it (final review m-7). * fix(maintain): keep the injected refreshStages path free of a real collector The m-2 fix built refreshedReport's shared collector unconditionally, even when deps.refreshStages was injected — a fully-injected test (refreshStages + service) used to trigger zero real collector or facade construction (defaultStages was bypassed entirely); it now dynamically imported footprint/index.mjs and constructed a real createSystemCollector() for nothing, contradicting the doc comment two lines above and the plan's hermeticity rule. Collector construction is now skipped outright when deps.refreshStages is injected: the half-injection guard already guarantees deps.service is present in that case, so nothing downstream would have read it anyway. Also adds the one test the review's own wording implies but the diff didn't yet prove: --refresh=live WITHOUT --only stays valid (runs the live stage, reads service.report(), exits 0).
1 parent 0fa5e48 commit e957737

124 files changed

Lines changed: 7658 additions & 1570 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/nightly.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
USERPROFILE: ${{ runner.temp }}/kit-home
6161
XDG_CONFIG_HOME: ${{ runner.temp }}/kit-home/.config
6262
APPDATA: ${{ runner.temp }}/kit-home/AppData/Roaming
63-
run: node bin/agentic-kit.mjs x verify security
63+
run: node bin/agentic-kit.mjs status --refresh=live --only security
6464

6565
- name: Host-neutral hook contract fixtures
6666
run: node --test tests/kit/hook-audit.test.mjs tests/kit/hook-audit-hosts.test.mjs
@@ -86,7 +86,7 @@ jobs:
8686
# that mitigation does not help (issuecomment-5857781254).
8787
# Scope is NOT neural-train-specific: upstream evidence (2026-08-12) shows the
8888
# same teardown abort on store-touching commands (`memory search` → correct
89-
# output, rc 134), so an `x verify memory` step added here would need the same
89+
# output, rc 134), so an `--only memory-routes` step added here would need the same
9090
# guard. Remove continue-on-error once that issue closes.
9191
- name: Deep proof against the live packages (learning)
9292
continue-on-error: true
@@ -95,7 +95,7 @@ jobs:
9595
USERPROFILE: ${{ runner.temp }}/kit-home
9696
XDG_CONFIG_HOME: ${{ runner.temp }}/kit-home/.config
9797
APPDATA: ${{ runner.temp }}/kit-home/AppData/Roaming
98-
run: node bin/agentic-kit.mjs x verify learning
98+
run: node bin/agentic-kit.mjs status --refresh=live --only learning
9999

100100
clean-mac-setup:
101101
name: clean macOS setup (packed artifact)

‎README.md‎

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ container for you. See [docs/DEVCONTAINERS.md](https://github.com/pacphi/agentic
4141
- **Multi-host execution (optional):** Claude, Codex, and opt-in OpenCode can share one activity policy; `ak run` is the canonical executor, while `ak setup --codex` enables the subscription-backed Claude/Codex defaults.
4242
- **Self-healing:** `ak sync` re-converges after every upgrade; `ak status` and a local dashboard report observed state and explicit evidence gaps.
4343
- **Managed ruflo components:** ak applies and reports ruflo's opt-in agent pickers, MCP tool governance, learning profile, and promotional funnel — see [Managed ruflo components](docs/MANAGED-TOOLS.md#managed-ruflo-components).
44-
- **Scoped verification:** `ak x verify` exercises named paths against real CLIs and reports
45-
their results; `ak status` shows each remembered result with its age, and `ak status --live`
46-
runs the quick, free subset first. Registration,
44+
- **Scoped verification:** `ak status --refresh=live` exercises named paths against real CLIs and
45+
reports their results; `ak status` shows each remembered result with its age, and a plain
46+
`--refresh=live` runs the quick, free subset first, while `--only CHECK` names one check
47+
(including a slow proof) directly. Registration,
4748
configuration, and one passing probe do not establish every capability or every running session.
4849
- Cross-platform, **zero runtime dependencies** (SQLite embedded).
4950

@@ -89,7 +90,7 @@ ak setup first-time setup — machine and/or the project you're standing
8990
[--codex] [--opencode] [--primary-host claude|codex] [--with-deja-vu]
9091
[--deja-vu-mode mcp|auto] [--no-deja-vu] [--project] [--minimal]
9192
[--yes] [--no-aqe] [--no-security] [--reconfigure]
92-
ak status read-only dashboard: what's true, what's drifted [--json] [--deep] [--live]
93+
ak status read-only dashboard: what's true, what's drifted [--json] [--refresh[=live|machine]]
9394
ak sync converge to good: upgrade + heal + verify [--dry-run] [--no-upgrade]
9495
[--skip SUBSYSTEM] [--json]
9596
ak dashboard open the local web dashboard (auto-opens your browser)
@@ -98,15 +99,16 @@ ak admin maintainer-only telemetry admin (localhost; GitHub/npm egress)
9899
[--port N] [--no-open]
99100
ak about what each installed component is and why it's there
100101
ak system machine footprint: install size, runtime, storage, catalog, projects
101-
[--deep] [--json]
102-
ak maintain inventory, guidance, discovery, guarded one-action plans
103-
inventory | show | guidance | discovery | sources | scans | activity | audit | reconcile | plan | apply | undo
102+
[--refresh[=live|machine]] [--json]
103+
ak maintain findings, guidance, discovery, guarded one-action plans
104+
[report] [--refresh[=live|machine]] | inventory | show | guidance | discovery |
105+
sources | scans | activity | audit | reconcile | plan | apply | undo
104106
ak usage offline scorecard, prompt patterns, and provider account cache
105107
status | score | prompts | refresh openrouter
106108
ak models inspect model lifecycle evidence and swap impact
107109
status | refresh | diff | explain | plan
108110
ak host manage execution hosts, routing, and provider bindings
109-
status | pick | refresh | off
111+
status | pick | reset-routes | off | check-connection
110112
ak audit hooks read-only hook inventory across Codex, Claude, OpenCode, and adapters
111113
ak audit context read-only managed-guidance, skill-metadata, MCP-registration, and window evidence
112114
ak heal hooks deterministic dry-run repair plan; explicit apply, verify, undo, recover
@@ -150,26 +152,29 @@ and current platform limits.
150152
| **models** | Builds a private, host-scoped model inventory from Claude, Codex, OpenCode, Ollama, bounded local usage evidence, and a dated bundled record of Anthropic's public model/lifecycle facts. `status`, `diff`, `explain`, and `plan` are cache-only and read-only; `refresh --online` is the sole online-catalogue boundary. Public facts never imply account or OpenRouter routability. Swap plans enumerate routes plus Agentic QE/Ruflo consumers and print a copyable canonical action without executing it. The CLI exposes exact local evidence deliberately; the Dashboard exposes source-proven public catalogue identity and uses the owner-visible model read contract; secret-shaped values remain masked. See [Model lifecycle intelligence](docs/MODELS.md). |
151153
| **admin** | Opens the **maintainer admin** (`127.0.0.1:7432`, localhost-only, foreground) — the project-telemetry sibling of `dashboard`, with the same dark/light visual theme and persisted theme preference: unique repo visitors and cloners (GitHub traffic API, needs a push-access token via `GITHUB_TOKEN`/`GH_TOKEN`/`gh auth token` — panels degrade honestly without one), contributors and watchers, npm download momentum (last 7d vs prior 7d, sparklines — shown as trend only, never an absolute reach number, since mirrors/CI inflate the raw count), latest CI run status and open Dependabot alerts, a **"since you last looked"** delta strip over a local baseline, open issues/PRs from others (oldest first), and external humans ranked by recency (bots excluded). Access is gated by a **per-session token** carried in the URL fragment and sent header-only; the page makes **zero external fetches** (the server proxies GitHub/npm; your credential never reaches the page or the payload). Where `dashboard` is offline-first, `admin` does deliberate GitHub/npm egress — that contract split is why they're siblings, not tabs. `--port N`, `--no-open`; Ctrl-C stops. (Also available as `ak x admin`.) |
152154
| **about** | A plain-words directory of every component the kit installs and configures — one entry per component: what it is, what it does for you, where to read more, and an honest state chip read from the same detection `ak status` uses (the prose is authored with the release; the chip is the only runtime fact). `ak about [entry-id]` opens one entry; `--category` narrows to `hosts`, `engine-memory`, `quality`, `safety`, `knowledge`, `kit`, or `configured`; `--no-detect` skips state resolution for an instant editorial read; `--json` emits the directory with resolved chips. The dashboard's About area renders this identical directory. |
153-
| **system** | What the stack occupies on your machine. The default read is the cheap tier: the live agent-process census, the files growing fastest between scans, and the last full scan's figures carried forward with their date. `--deep` re-walks install trees, storage, the cross-host catalog, and the hosted repositories with recorded sessions, then persists the result; excluded local-only, unsupported-remote, and sessionless project candidates remain counted with reasons. Production runs this synchronous measurement in one worker so the dashboard can continue reporting activity; this is responsiveness containment, not a claim that the scan finishes sooner. `--json` emits the same snapshot payload `/api/system` serves. |
154-
| **maintain** | Inventory-led maintenance. `inventory`, `show`, `guidance`, and `procedure` read the verified placement inventory and the outcomes the kit can ground; `discovery`, `sources`, and `scans` manage where it looks and resumable scan coverage; `activity`, `receipt`, and `audit` read receipts and run the read-only interruption audit. `ak maintain scan` runs the provider check; add `--deep` to remeasure System first and `--refresh-inventory` to rebuild the inventory. Every write is one action: `plan --executable` derives one action, `apply` needs the plan ID, digest, one action ID, and `--yes`, `undo` needs a committed reversible receipt, and `reconcile` records one audited outcome for one receipt. `recover` is a read-only alias for `audit`. Placements without a registered provider stay report-only. See [Maintenance](docs/MAINTENANCE.md). |
155+
| **system** | What the stack occupies on your machine. The default read is the cheap tier: the live agent-process census, the files growing fastest between scans, and the last full scan's figures carried forward with their date. `--refresh=machine` re-walks install trees, storage, the cross-host catalog, and the hosted repositories with recorded sessions, then persists the result; `--project-trees` also measures the working trees of your own projects; excluded local-only, unsupported-remote, and sessionless project candidates remain counted with reasons. Production runs this synchronous measurement in one worker so the dashboard can continue reporting activity; this is responsiveness containment, not a claim that the scan finishes sooner. `--json` emits the same snapshot payload `/api/system` serves. |
156+
| **maintain** | Inventory-led maintenance. `inventory`, `show`, `guidance`, and `procedure` read the verified placement inventory and the outcomes the kit can ground; `discovery`, `sources`, and `scans` manage where it looks and resumable scan coverage; `activity`, `receipt`, and `audit` read receipts and run the read-only interruption audit. `ak maintain` (or `ak maintain report`) reads the last measurement; `--refresh[=live\|machine]` refreshes Maintenance evidence and the inventory first, adding live checks or a full machine re-measure as named. Every write is one action: `plan --executable` derives one action, `apply` needs the plan ID, digest, one action ID, and `--yes`, `undo` needs a committed reversible receipt, and `reconcile` records one audited outcome for one receipt. `recover` is a read-only alias for `audit`. Placements without a registered provider stay report-only. See [Maintenance](docs/MAINTENANCE.md). |
155157
| **run** | **Canonical execution surface.** Executes the template vocabulary through host-neutral supervised adapters. It accepts an explicit OpenCode route (persisted or `--route`) alongside Claude/Codex; `--dry-run` prints the exact static plan (with each worker's escalation ladder); at runtime, successful dependencies pass runtime-only, sanitized handoffs capped at 2 KiB each/8 KiB fan-in, never exposed in public JSON. A handoff may cross hosts/vendors and must exclude secrets, credentials, raw logs, and transcript excerpts. `--escalate` advances a failed worker one rung of its route's ladder per attempt (bounded by the ladder; permission/consent and uncertain results are never escalated). `--timeout` is one absolute readiness→prepare→launch→observe budget per attempt, while separately bounded teardown proves whether resources terminated. An OpenCode worker runs an isolated loopback server with ephemeral basic authentication, returns only normalized observed facts, and aborts instead of approving a permission request. `ak run` does not turn OpenCode into an AQE provider or primary host. |
156-
| **host** | Execution-host status, selection, primary-host choice, activity routing, and reversible teardown: `ak host status\|pick\|refresh\|off`. The plumbing spelling is `ak x host`. Inference providers and bindings remain separate concepts even though their controls share this workflow. |
158+
| **host** | Execution-host status, selection, primary-host choice, activity routing, reversible teardown, and the consent-gated connection check: `ak host status\|pick\|reset-routes\|off\|check-connection`. The plumbing spelling is `ak x host`. Inference providers and bindings remain separate concepts even though their controls share this workflow. |
157159
| **uninstall** | Removes the kit's footprint (and any legacy shell-kit install); owned configuration is removed and ak's receipted edits inside Ruflo's install are put back, while project memory/transcripts are retained by default; `--purge` widens the documented package/config scope. |
158160

159161
</details>
160162

161163
Power-user mechanisms live under `ak x …` (`daemon-gc`, `harvest`,
162-
`mcp pick|off`, `host status|pick|refresh|off`, `reference diff|sync`,
163-
`statusline status|codex native|extended|off`,
164-
`verify learning|security|aqe|providers|harvest`, `improvement-eval`) — see `ak --help --all`.
164+
`mcp status|pick|off`, `host status|pick|reset-routes|off|check-connection`, `reference diff|sync`,
165+
`statusline status|codex native|codex extended|codex off`,
166+
`improvement-eval`) — see `ak --help --all`. Named checks and slow proofs (`learning`, `security`,
167+
`aqe`, `providers`, `harvest`, `deja-vu`, `memory`, `memory-routes`, `mcp`, `aqe-embedding`) run
168+
through `ak status --refresh=live --only CHECK`.
165169

166170
One of those is worth calling out:
167171

168172
- **`ak x harvest`** — an **opt-in** (`kit.json` `harvest:true`), foreground learning-*write*:
169173
it records the session outcome through Ruflo's own `ruflo hooks post-task`, run from the
170174
project root with the project memory pin; `--distill` also runs Ruflo's memory distillation
171175
(`ruflo memory distill run`) on the project store. Off and `--dry-run`-safe by default; no
172-
daemon, ever. `ak x verify harvest` proves the path against an isolated temporary store.
176+
daemon, ever. `ak status --refresh=live --only harvest` proves the path against an isolated
177+
temporary store.
173178

174179
## The status line
175180

0 commit comments

Comments
 (0)