Skip to content

feat(core): configRead {kind,name} — complete the configList registry contract (T-401)#64

Merged
matze4u merged 3 commits into
mainfrom
feat/v1-0-config-read
Jun 2, 2026
Merged

feat(core): configRead {kind,name} — complete the configList registry contract (T-401)#64
matze4u merged 3 commits into
mainfrom
feat/v1-0-config-read

Conversation

@matze4u

@matze4u matze4u commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

What

Completes the configList agent-config registry contract (ADR-050) with its read sibling, configRead {kind, name}{kind, name, source, body}. This mirrors the commandList + commandRead PAIR (ADR-048) — the command council had explicitly required BOTH because a list whose items the IDE cannot open into a detail pane is "half a contract". configList was exactly that half-contract for skills + rules + commands.

How

  • ProtocolConfigReadRequest {kind,name}, ConfigReadResponse {kind,name,source,body}, and a local-only ConfigSource enum ('local' | 'missing', no mcp member, unlike CommandSource). Registered configRead in the Methods registry + hand-maintained codegen descriptors (67 → 69 Kotlin DTOs).
  • CoreConfigHandler.read reads the body straight off the same walk-once cache configList groups, so list and read can never disagree. Local-only by design: the body is already parsed onto every walked node for all three kinds; MCP has skill_read/command_read but no rule_read, so an MCP-first path would be asymmetric. A miss is source: 'missing' with an empty body (no throw, mirrors commandRead). Matching is on the display name (frontmatter name ?? slug) via a shared displayName helper, so list/read key identically. Dispatcher route behind the existing requireConfig() gate.

Council

codex-cli 0.134.0 + gemini-cli 0.41.2, run serially. UNANIMOUS Q0–Q3 = A: wire now (complete the contract) / {kind,name} key (names collide across kinds) / local-only / mirror commandRead. Q4 → full body uncapped (consistency with commandRead). Q5 traps satisfied by design (shared walk cache → no disagreement; in-memory match → no path traversal).

Verification

  • task ci exit 0 — lint, format, build, typecheck, test (core 1147 pass / 1 skip, +15).
  • task jetbrains:check BUILD SUCCESSFUL (the +2 Kotlin DTOs compile).
  • No checkbox flip — the skill picker / rules viewer detail-pane render remains an IDE surface; this is the headless body data path it will call.

See ADR-052.

matze4u added 3 commits June 2, 2026 14:32
Completes the configList contract (ADR-050) with its read sibling, mirroring
the commandList+commandRead pair (ADR-048). ConfigReadRequest {kind,name},
ConfigReadResponse {kind,name,source,body}, and a local-only ConfigSource
enum ('local'|'missing', no 'mcp'). Registers configRead in the Methods
registry and the hand-maintained codegen descriptors (67->69 Kotlin DTOs).
…401)

ConfigHandler.read reads the artifact body off the same walk-once cache
configList groups, so list and read can never disagree. Local-only: a node
hit is source 'local', a miss is 'missing' with an empty body (no throw,
mirrors commandRead). Matches the DISPLAY name (frontmatter name ?? slug) via
a shared displayName helper so list/read key identically. Dispatcher route
behind the existing requireConfig() gate. +15 core tests (read per-kind,
kind disambiguation, display-name match, missing, fail-open, shared cache;
sidecar live-wiring over a temp tree).
Council codex+gemini UNANIMOUS Q0-Q3=A (wire now / {kind,name} key /
local-only / mirror commandRead). No checkbox flip — the detail-pane render
stays an IDE surface.
@matze4u matze4u merged commit 69a41bc into main Jun 2, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant