Skip to content

Commit 796b904

Browse files
authored
feat: add capability-driven integration adapters (#74)
* feat: add capability-driven integration adapters * docs: define domain language and context map * fix: separate dashboard host and provider identity * docs: clarify ADR 0011 and 0016 boundary * fix: cascade dashboard relative-time labels beyond hours The Live Sessions project list showed raw hour counts (e.g. "999h ago") with no upper bound. Roll over into days past 24h, weeks past 7d, and years past 52w so long-idle projects read as "41d 15h ago" instead. * Revert "fix: cascade dashboard relative-time labels beyond hours" This reverts commit 620fe22.
1 parent 125563d commit 796b904

72 files changed

Lines changed: 3393 additions & 264 deletions

Some content is hidden

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

‎README.md‎

Lines changed: 33 additions & 8 deletions
Large diffs are not rendered by default.

‎bin/agentic-kit.mjs‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ const PORCELAIN = Object.assign(Object.create(null), {
2222
dashboard: () => import('../src/commands/x/dashboard.mjs'),
2323
admin: () => import('../src/commands/x/admin.mjs'),
2424
dual: () => import('../src/commands/dual.mjs'),
25+
host: () => import('../src/commands/x/provider.mjs'),
26+
provider: () => import('../src/commands/x/provider.mjs'),
2527
uninstall: () => import('../src/commands/uninstall.mjs'),
2628
});
2729

@@ -31,6 +33,7 @@ const PLUMBING = Object.assign(Object.create(null), {
3133
'dashboard': () => import('../src/commands/x/dashboard.mjs'),
3234
'harvest': () => import('../src/commands/x/harvest.mjs'),
3335
'mcp': () => import('../src/commands/x/mcp.mjs'),
36+
'host': () => import('../src/commands/x/provider.mjs'),
3437
'provider': () => import('../src/commands/x/provider.mjs'),
3538
'reference': () => import('../src/commands/x/reference.mjs'),
3639
'statusline': () => import('../src/commands/x/statusline.mjs'),
@@ -47,6 +50,8 @@ Usage (ak = alias of agentic-kit):
4750
ak dashboard open the local web dashboard (localhost; auto-opens browser) [--port N] [--no-open]
4851
ak admin maintainer-only telemetry admin (localhost; GitHub/npm egress) [--port N] [--no-open]
4952
ak dual run a Claude+Codex collaboration swarm (dual-host) [run <template> "task"] [--dry-run]
53+
ak host manage agent hosts, routing, and provider bindings [status|pick|refresh|off]
54+
ak provider deprecated alias for ak host; removed before the stable release
5055
ak uninstall leave cleanly [--this-project] [--purge]
5156
5257
When in doubt: ak sync
@@ -67,7 +72,8 @@ Plumbing (power users) — each takes --help:
6772
ak x dashboard [--port N] read-only local health dashboard (localhost only)
6873
ak x harvest [--dry-run] opt-in learning-write: replay experiences into the substrate
6974
ak x mcp [status|pick|off] MCP registration + tool-family deny rules
70-
ak x provider [status|pick|off] detect claude/codex CLIs; wire ruflo + aqe hosts/providers
75+
ak x host [status|pick|refresh|off] manage hosts, routing, and provider bindings
76+
ak x provider [status|pick|refresh|off] deprecated alias; removed before the stable release
7177
ak x reference [diff|sync] CLAUDE.md managed-block inspection/reconcile
7278
ak x statusline [status|codex native|codex extended|codex off] manage Codex's native user status line
7379
ak x verify [learning|security|aqe|providers|harvest|all] deep proofs (slow, spawns real CLIs)
@@ -80,6 +86,7 @@ async function main() {
8086
const argv = process.argv.slice(2);
8187
let cmd = argv[0];
8288
let rest = argv.slice(1);
89+
let deprecatedProvider = cmd === 'provider';
8390

8491
if (cmd === '--help' || cmd === '-h' || cmd === 'help') {
8592
console.log(argv.includes('--all') ? HELP_ALL : HELP);
@@ -97,6 +104,7 @@ async function main() {
97104
table = PLUMBING;
98105
cmd = rest[0];
99106
rest = rest.slice(1);
107+
deprecatedProvider = cmd === 'provider';
100108
// `ak x`, `ak x --help`, `ak x -h` → the plumbing index.
101109
if (!cmd || cmd === '--help' || cmd === '-h') { console.log(HELP_ALL); return 0; }
102110
if (cmd === 'improvement-eval') {
@@ -120,6 +128,11 @@ async function main() {
120128
return 2;
121129
}
122130

131+
if (deprecatedProvider) {
132+
const legacy = argv[0] === 'x' ? 'ak x provider' : 'ak provider';
133+
const canonical = argv[0] === 'x' ? 'ak x host' : 'ak host';
134+
console.error(`${legacy} is deprecated; use \`${canonical}\`. It will be removed before the stable release.`);
135+
}
123136
const mod = await table[cmd]();
124137

125138
// Per-command help — intercepted BEFORE run() so mutating commands

‎claude/aqe-reference.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ called first**, e.g. `fleet_init({ topology:"hierarchical", maxAgents:15, memory
4646
(metered API key), or `ollama`/`onnx` (local). It normalizes `anthropic`→`claude` and ignores
4747
unknown values. `AQE_MAX_BUDGET_USD` (or `--max-budget-usd`) caps metered spend; `aqe health`
4848
shows an "LLM Billing" section saying who pays. `aqe init` never writes these — but
49-
**`ak x provider pick` now manages `AQE_LLM_PROVIDER` for you** (into
49+
**`ak host pick` now manages `AQE_LLM_PROVIDER` for you** (into
5050
`.claude/settings.local.json` `env`, reversibly), and can write an ordered **fallback chain**
5151
into `.agentic-qe/llm-config.json` from `kit.json` (`--aqe-fallback 'claude-code:claude-opus-5; openai:gpt-5.6'`) —
5252
keys stay in the env, never the file. aqe is NOT limited to claude-code: codex the *CLI* isn't a

‎claude/dual-mode-reference.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fallback.
1717
### `ak dual run` — Claude+Codex collaboration pipelines
1818

1919
`ak dual run <template> "<task>"` materializes a multi-worker pipeline from your
20-
per-activity routing policy (set via `ak x provider`) and runs it through the
20+
per-activity routing policy (set via `ak host`) and runs it through the
2121
`claude-flow-codex` adapter. Each worker is assigned a host + model by the policy, so a
2222
single run can span both vendors.
2323

@@ -52,12 +52,12 @@ Register (or repair) both directions with `ak sync`; inspect with `ak status`.
5252
### Per-activity routing + escalation ladders
5353

5454
Routing is **per activity**, not per session — coder/tester lean Codex, reviewer and
55-
security-analysis lean Claude, and so on (`ak x provider` shows and edits the table).
55+
security-analysis lean Claude, and so on (`ak host` shows and edits the table).
5656
`--escalate` walks a **cross-vendor** ladder: a failed step retries on the other vendor's
5757
stronger model, so a Codex miss escalates into Claude (and vice-versa) rather than just
5858
burning retries on the same engine.
5959

60-
**Which host leads.** The two are peers, but `ak x provider pick --primary-host claude|codex`
60+
**Which host leads.** The two are peers, but `ak host pick --primary-host claude|codex`
6161
(default `claude`) picks which one leads: codex-primary **mirrors** the default table so Codex
6262
takes the reasoning/review lead and Claude becomes the alternate/escalation target — the same
6363
ambidextrous experience with the roles flipped. `ak status` marks the primary and **fails**

‎claude/providers-reference.md‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,19 @@ agentic-qe to use one or both. Two independent axes:
1919
- **ruflo** — `anthropic` / `openai` / `google` / `ollama` via `ruflo providers configure`.
2020
- API keys live in the environment; they are never persisted to `kit.json`.
2121

22+
During the alpha, `ak host` is the canonical namespace for execution-host lifecycle and
23+
selection; `ak x host` is its plumbing spelling. `ak provider` and `ak x provider` are deprecated
24+
compatibility aliases that warn on stderr and will be removed before stable. This does not rename
25+
inference providers or bindings into hosts; provider flags remain temporarily co-located on this
26+
workflow while dedicated capability-driven surfaces mature.
27+
2228
**One or several — you're never forced to pick just one.** All three surfaces run multiple
2329
providers concurrently:
2430
- **ruflo hosts** — enable `claude` *and* `codex` together (dual-mode); ruflo runs both.
2531
- **ruflo LLM providers** — a list, with load-balancing + automatic failover.
2632
- **agentic-qe** — its `HybridRouter` **auto-enables every provider that has an API key in the
2733
env** and fails over across an ordered chain. `AQE_LLM_PROVIDER` only pins the *default* (the
28-
primary) — the others stay enabled. So `ak x provider` sets aqe's primary; adding
34+
primary) — the others stay enabled. So `ak host` sets aqe's primary; adding
2935
`OPENAI_API_KEY` / `GEMINI_API_KEY` to the env brings those online as fallbacks automatically.
3036

3137
### aqe fallback chain — managed from `kit.json`
@@ -34,7 +40,7 @@ For **deterministic** ordering (rather than relying on env auto-enable), `ak` wr
3440
`.agentic-qe/llm-config.json` from `kit.json`:
3541

3642
```bash
37-
ak x provider pick --aqe-provider claude-code \
43+
ak host pick --aqe-provider claude-code \
3844
--aqe-fallback 'claude-code:claude-opus-5; openai:gpt-5.6; gemini:gemini-3.5-flash'
3945
```
4046

@@ -43,16 +49,16 @@ priority; model IDs are examples current as of July 2026 — use what your provi
4349
ak writes a **complete** chain (aqe merges it shallowly, so partial chains would drop
4450
defaults), sets each provider `enabled`, and tags the file `_managedBy: agentic-kit`. **API keys
4551
are never written** — they stay in the env (aqe refuses to persist them anyway). `ak sync`
46-
reapplies the chain; `ak status` flags drift; `ak x provider off` restores the pre-ak file from
52+
reapplies the chain; `ak status` flags drift; `ak host off` restores the pre-ak file from
4753
its one-time `.bak` (or removes an ak-created file). Entries need populated models — aqe's router
4854
skips an entry with none. For lower-level edits, `aqe llm-router config` still works.
4955

5056
### Managing it (prompts-once, reversible)
5157

5258
```bash
53-
ak x provider status # detected CLIs + versions, what's enabled, what's wired
54-
ak x provider pick # choose ruflo hosts / aqe provider / ruflo API providers → persist → apply
55-
ak x provider off # reset to claude-only default; strip managed env keys
59+
ak host status # detected CLIs + versions, what's enabled, what's wired
60+
ak host pick # choose ruflo hosts / aqe provider / ruflo API providers → persist → apply
61+
ak host off # reset to claude-only default; strip managed env keys
5662
```
5763

5864
`pick` persists your choice to `kit.json` and applies it: it writes the ruflo backend flags
@@ -70,7 +76,7 @@ dual-mode reference block and `docs/PROVIDERS.md` §3.5 for the routing table an
7076

7177
### Install & update (install-method-aware)
7278

73-
- **First install** — `ak setup` (and `ak x provider pick`) installs any *enabled* host that
79+
- **First install** — `ak setup` (and `ak host pick`) installs any *enabled* host that
7480
is entirely **absent**: `npm i -g @anthropic-ai/claude-code` / `@openai/codex`.
7581
- **Updates** — `ak sync` keeps **npm-managed** hosts current (drift is detected on the same
7682
cached TTL as ruflo/aqe, and surfaces in the bin nudge + `ak status`).

‎docs/LIVE-SESSIONS.md‎

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,15 @@ request. Stopping the dashboard closes the live service and all clients.
3434

3535
- Claude and Codex sessions discovered newest-first from their local JSONL
3636
stores and bootstrapped from bounded, metadata-only records.
37-
- Project-first session cards with a provider glyph and text, model when
38-
reported, lifecycle, freshness, and a concise operational summary.
37+
- Project-first session cards with a host glyph and name, independently
38+
evidenced inference provider/model when reported, lifecycle, freshness, and
39+
a concise operational summary.
3940
- Session, agent, sub-agent, tool, skill, plugin, MCP, and gate entities when a
4041
supported source record identifies them.
4142
- Authoritative Codex parent/child edges from the Codex state ledger.
4243
- Human-readable identity and current work: resolved agent or capability name,
43-
host/model, lifecycle, elapsed time, latest safe operation summary, and
44-
evidence confidence.
44+
host, provider/model, lifecycle, elapsed time, latest safe operation summary,
45+
and evidence confidence.
4546
- Typed relationships whose accessible titles use verbs such as **spawned**,
4647
**delegated**, **invoked**, **returned**, **evaluated**, and **gated**.
4748
- A semantic execution canvas with stable agent anchors and bounded tool,
@@ -57,8 +58,9 @@ request. Stopping the dashboard closes the live service and all clients.
5758
actor-specific geometry, and a **Pause live** control.
5859
- Sanitized adapter health showing status and aggregate file/event/error counts.
5960

60-
The overview answers which project/provider is involved, whether the evidence
61-
is current, who is active, and what operation is happening now. Selecting a
61+
The overview answers which project and host are involved, which inference
62+
provider is evidenced, whether the evidence is current, who is active, and
63+
what operation is happening now. Selecting a
6264
node highlights adjacent relationships, focuses its work, and synchronizes the
6365
transcript. Search filters the current stream. Auto-follow yields when the
6466
reader scrolls away and reports unread activity until following resumes. The
@@ -67,7 +69,7 @@ flow downward. Follow anchors to the top; playback remains chronologically
6769
ordered internally.
6870

6971
Projects are the durable top-level grouping. Select a project first, then one
70-
of its provider-qualified root sessions; currently active sessions appear
72+
of its host-qualified root sessions; currently active sessions appear
7173
before recent completed sessions. Selecting a root reveals its agent/worker
7274
threads as an indented hierarchy. Those child threads remain selectable for
7375
their own map, transcript, and playback, but do not inflate the project's
@@ -195,13 +197,13 @@ that the dashboard has inspected an agent's private reasoning.
195197

196198
The topology plane is constructed from an allowlist and contains no transcript
197199
bodies. The separately selected content plane intentionally carries rich local
198-
evidence. It parses provider records into a bounded DTO, masks every emitted
200+
evidence. It parses source records into a bounded DTO, masks every emitted
199201
string server-side, and never emits Codex `encrypted_content`. Secret masking
200202
is best effort, not a guarantee; only run the dashboard where its local
201203
transcripts may be viewed.
202204

203205
Transcript lookup validates both host and session ID, resolves the real file
204-
beneath the configured provider root, rejects symlink escapes, and rechecks
206+
beneath the configured host transcript root, rejects symlink escapes, and rechecks
205207
containment after replacement. Content responses are `no-store`, same-origin,
206208
bounded, and destroyed after their last subscriber.
207209

@@ -246,7 +248,7 @@ unbounded content snapshot.
246248
| Symptom | Explanation |
247249
|---------|-------------|
248250
| No sessions | No supported metadata was found within the bounded newest-first discovery set |
249-
| Many identical provider session rows | Refresh after the current snapshot reconciles ledger hierarchy; root sessions and nested worker threads are counted separately |
251+
| Many identical host session rows | Refresh after the current snapshot reconciles ledger hierarchy; root sessions and nested worker threads are counted separately |
250252
| Worker thread appears at top level | Its declared parent is not currently retained, so it remains navigable as an orphan rather than hiding evidence |
251253
| Ruflo or AQE absent | Their stores are not auto-discovered; register each JSONL file with `--live-source` |
252254
| Project name not reported | No supported metadata supplied a working directory; raw paths are never sent to the browser |

‎docs/LOCAL-MODEL-VALIDATION.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ specifications, not observed** — at research time (2026-07-27) the Ollama daem
1111
indexed transcripts on the reference machine were vendor-metered. This document is the experiment
1212
that replaces derivation with measurement.
1313

14+
[ADR-0016](adr/0016-capability-driven-integration-adapters.md) names the relationship this
15+
exercise is intended to prove: `ollama-via-claude` and `ollama-via-codex` are two independent
16+
**bindings** to one Ollama **provider**, while Claude Code and Codex CLI remain the transcript
17+
**hosts**. The catalogue/runtime API is a separate **observability source**. Configuring a binding
18+
establishes configured provenance; it does not upgrade provider, model digest, token, cache, quota,
19+
or `$0` claims to observed. This document remains that evidence gate.
20+
1421
**Time:** about 15 minutes of interactive work, plus two paste-backs.
1522

1623
---

‎docs/MANAGED-TOOLS.md‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ version-detected, and displayed. This doc states the contract's four
55
invariants, maps every managed tool onto them, and gives the checklist for
66
adding a new tool without breaking them.
77

8+
The **host** rows here mean execution drivers such as Claude Code, Codex CLI, and OpenCode.
9+
Inference **providers** such as OpenRouter and Ollama are not install-owned hosts. Provider intent
10+
may use a **binding** and native configuration **projection**, while transcripts and catalogues
11+
remain separate **observability** evidence. The shared lifecycle and value-precise ownership
12+
design is Proposed in [ADR-0016](adr/0016-capability-driven-integration-adapters.md).
13+
814
Each invariant traces to a live failure it prevents — the appendix records
915
them.
1016

@@ -46,7 +52,7 @@ them.
4652
| --- | --- | --- | --- | --- | --- |
4753
| **ruflo** | npm `ruflo@latest` | `ak sync` | disk: global `package.json` | npm `view latest` (TTL-cached) | row ✓ / upstream's own `RuFlo V<x>` header ✓ / card + banner ✓ |
4854
| **agentic-qe** | npm `agentic-qe@latest` | `ak sync` | disk: global `package.json` (project-local fallback) | npm `view latest` (TTL-cached) | row ✓ / `Agentic QE V<x>` chip ✓ / card + banner ✓ |
49-
| **hosts** (claude, codex) | npm `@latest` — only when npm-managed | `ak sync` if npm-installed; **explicitly disowned** if brew/mise/native | disk: global `package.json`, else `--version` probe | npm latest for npm-managed only; external → `outdated:false` | row ✓ (version + method) / n/a / card + banner (npm-managed only) ✓ |
55+
| **hosts** (currently Claude/Codex; OpenCode is non-routable) | npm `@latest` — only when npm-managed | `ak sync` if npm-installed; **explicitly disowned** if brew/mise/native | disk: global `package.json`, else `--version` probe | npm latest for npm-managed only; external → `outdated:false` | row ✓ (version + method) / n/a / card + banner (npm-managed only) ✓ |
5056
| **agentdb** | npm, **pinned to ruflo's bundled version** — deliberately not latest | `ak sync` (repins on core skew) | disk: global `package.json` | ruflo's **bundled** copy (coherence), not npm latest — by design | row ✓ / n/a / card ✓; banner excluded (its authority isn't "latest") |
5157
| **ruvnet-brain** | npm `ruvnet-brain@latest` + `--version v<tag>` pin (never `github:` HEAD) | `ak sync`; the installer's own nightly self-updater is suppressed at install (`--no-nightly-prompt`) and disabled by sync if found (`ruvnet-brain-nightly` subsystem) | disk: KB `SOURCE.json → releaseTag`, falling back to ak's kit.json stamp for pre-stamping bundles | GitHub `releases/latest` tag (TTL-cached) | row ✓ / `V<tag>` chip ✓ / card + banner ✓ |
5258
| **kit (self)** | npm, **pinned to the exact version drift saw** (`@pacphi/agentic-kit@<v>`) | `ak sync` (runs last — npm replaces the running code) | disk: running copy's `package.json` | npm `latest` (+ `next` for prereleases, TTL-cached) | row ✓ / n/a / header version + card + banner ✓ |

0 commit comments

Comments
 (0)