Skip to content

docs(witan): give the two colliding ADRs their own numbers - #253

Open
blarghmatey wants to merge 4 commits into
mainfrom
witan-adr-renumber
Open

docs(witan): give the two colliding ADRs their own numbers#253
blarghmatey wants to merge 4 commits into
mainfrom
witan-adr-renumber

Conversation

@blarghmatey

Copy link
Copy Markdown
Member

Numbers 0004 and 0006 were each used by two different decisions:

0004 Keycloak JWT per-user actor mapping ← keeps 0004
0004 Optional task phase field → 0008
0006 Code-graph branch ownership + reaping ← keeps 0006
0006 Stateless MCP protocol era → 0009

ADRs are cross-referenced by number from code comments, other ADRs, and
changelog entries ("see ADR-0005", "Related: ADR-0002"), so a duplicated
number makes those references ambiguous — a reader following "ADR-0006" cannot
tell which document is meant.

Which of each pair kept its number was decided by reference count, so the
renumber moves the fewest citations: keycloak carries 10 by-filename
references (and every bare ADR-0004 in the tree is about identity — oidc.py,
identity.py, omnigraph.py, config.py) against 1 for the phase tag; branch
ownership carries 7 against 4 for the stateless era.

This lands before the documentation site rather than after it deliberately.
Once the site publishes, /explanation/decisions/0006-stateless-.../ is a URL
people link to and search engines index, and renumbering then would break
those. Doing it first also means the site ships correct numbers from its first
build instead of carrying a note explaining the collision.

Two references needed judgement beyond a path rewrite:

  • witan/config.py had a bare ADR-0006 meaning the stateless era. Left
    alone it would have silently started pointing at branch ownership.
  • The changelog entry for the stateless work named both the number and the
    path. A changelog is a historical record, so the entry now reads "ADR-0009
    (…, numbered 0006 at the time)" rather than being quietly rewritten to look
    as though it always said 0009.

Verified: no reference to either old filename remains anywhere in the tree, no
ADR number is used twice, and witan-council's 839 tests pass.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_017oVnpzjRJQVWq9hJGE2Rs7


Stack created with GitHub Stacks CLIGive Feedback 💬

…eceive

62 of 200 tool parameters across 25 tools shipped with no description.

FastMCP builds a tool's JSON Schema from its docstring's numpydoc `Parameters`
section, and a parameter with no entry there gets no `description` in the
schema. That schema is what reaches the model — so an agent calling
`task_update` was choosing among 12 undescribed parameters with nothing but
names and types to go on, and `recall` shipped nine undescribed seeds and
knobs. This is tool-calling accuracy, not documentation polish, which is why
it ships on its own ahead of the docs-site work that found it.

The descriptions record what a parameter *does to the graph* rather than
restating its name. The ones that carry real information:

- `task_update.status` — `in_progress` stamps a fresh lease and `closed`
  unblocks the task's dependents, so it is not a plain field write. Points at
  `task_claim`/`task_close`, which carry the ownership checks it does not.
- `task_update.parent` — written as the `parent_slug` field and the `ParentOf`
  edge in one commit, so a concurrent reader never sees the task parented one
  way and not the other.
- `memory_update.tags` — tags removed here keep their `Tagged` edge, because
  edges cannot be individually retracted and dropping the Topic would take out
  every other memory's edge to it.
- `recall.hops` — clamped 0–2; each hop widens results faster than it deepens
  them.
- `store_merge.dry_run` — the only way to see which side wins each
  `(type, slug)` before the graph changes.
- `task_link`/`task_unlink` `from_slug`/`to_slug` — direction is the common
  mistake and it decides which task `task_ready` withholds.
- `code_*` `symbol_id` — says where the value comes from and what shape it has,
  rather than assuming the caller already knows.

Verified: 839 witan-council + 516 witan-code tests pass, and the count of
undescribed parameters is 0.

The lone one-line hunk in server.py is a blank line `ruff format` wanted; it
predates this change and the hook applied it because this commit touches the
file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017oVnpzjRJQVWq9hJGE2Rs7
Copilot AI balanced review requested due to automatic review settings August 19, 2026 16:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Renumbers duplicate Witan ADRs and updates related references.

Changes:

  • Renumbers the phase ADR from 0004 to 0008.
  • Renumbers the stateless protocol ADR from 0006 to 0009.
  • Updates selected citations and preserves historical changelog context.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
mcp/servers/witan/witan/config.py Updates the stateless-era citation.
mcp/servers/witan/docs/adr/0009-stateless-mcp-protocol-era.md Renumbers the stateless protocol ADR.
mcp/servers/witan/docs/adr/0008-optional-task-phase-tag.md Renumbers the optional phase ADR.
mcp/servers/witan/docs/adr/0005-secure-cli-path-into-deployed-witan.md Updates stateless ADR links.
mcp/servers/witan/docs/adr/0004-keycloak-jwt-per-user-actor-mapping.md Updates its stateless ADR link.
mcp/servers/witan/CHANGELOG.md Records the new and historical ADR numbers.
Suppressed comments (1)

mcp/servers/witan/docs/adr/0009-stateless-mcp-protocol-era.md:1

  • Using 0009 creates another ambiguous identifier: ol-infrastructure's ADR-0009 is already cited by bare number in this tree (for example, 0005-secure-cli-path-into-deployed-witan.md:34,100 and 0007-local-to-shared-store-migration-transport.md:33,35). Those references now coexist with this local ADR-0009 and can no longer be resolved by number alone—the ambiguity this PR is intended to eliminate. Please use an unused number or qualify every existing ADR-0009 citation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread mcp/servers/witan/witan/config.py
blarghmatey and others added 2 commits August 19, 2026 12:22
…our the code does not have, and guard the surface with a test

Review feedback on #252 (Copilot). Both claims were verified against the code
before changing anything; both were wrong.

**`repo=""` does not fan out in witan-code.** The new `repo` descriptions on
`code_find_definition` and `code_search_symbol` said an empty string forces a
fan-out across every indexed repo. `_resolve_clients` tests `if repo:`, so `""`
is falsy and behaves exactly like omitting the argument: the current repo when
one is detected, all repos only when none is. The empty-string convention is
real in the witan memory/task tools and I carried it across to witan-code,
where it does not hold — which would have given agents silently partial
results. The descriptions now state the actual rule and flag the difference.

**Re-parenting leaves the old edge behind.** `task_update.parent`'s description
claimed field and edge stay consistent. The one-commit atomicity is real, but
`task_update` only issues `link_parent_of` — it never retracts a previous
`ParentOf` — so re-parenting an already-parented task moves `parent_slug` while
the old edge remains, and the task is reachable from both parents. That is a
permanent inconsistency, not the transient one the wording implied. Documented,
with a pointer to `task_unlink(kind="parent")`.

The underlying re-parent behaviour is left alone deliberately: retracting the
old edge is a behaviour change with test implications, not a docstring fix, and
it belongs in its own change rather than being folded into this one.

**Added the regression test the reviewer asked for**, in both packages. It
walks every registered tool and asserts each exposed parameter has a non-empty
`description`, so the 62 gaps this PR closed cannot silently return — the
existing `list_tools` coverage asserts tool names only. Asserted over the whole
surface rather than a fixed list, so a new tool is covered on registration.

Each file carries a second test asserting the inspection found a plausible
number of parameters: an empty listing would make the real assertion vacuous
and report success, which is the failure mode a guard like this actually has.

Verified the guard by removing one description: it fails naming
`task_update.slug`, and passes again when restored. 847 witan-council + 518
witan-code tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017oVnpzjRJQVWq9hJGE2Rs7
Numbers 0004 and 0006 were each used by two different decisions:

  0004  Keycloak JWT per-user actor mapping   ← keeps 0004
  0004  Optional task `phase` field           → 0008
  0006  Code-graph branch ownership + reaping ← keeps 0006
  0006  Stateless MCP protocol era            → 0009

ADRs are cross-referenced by number from code comments, other ADRs, and
changelog entries ("see ADR-0005", "Related: ADR-0002"), so a duplicated
number makes those references ambiguous — a reader following "ADR-0006" cannot
tell which document is meant.

Which of each pair kept its number was decided by reference count, so the
renumber moves the fewest citations: keycloak carries 10 by-filename
references (and every bare `ADR-0004` in the tree is about identity — oidc.py,
identity.py, omnigraph.py, config.py) against 1 for the phase tag; branch
ownership carries 7 against 4 for the stateless era.

This lands before the documentation site rather than after it deliberately.
Once the site publishes, `/explanation/decisions/0006-stateless-.../` is a URL
people link to and search engines index, and renumbering then would break
those. Doing it first also means the site ships correct numbers from its first
build instead of carrying a note explaining the collision.

Two references needed judgement beyond a path rewrite:

- `witan/config.py` had a bare `ADR-0006` meaning the stateless era. Left
  alone it would have silently started pointing at branch ownership.
- The changelog entry for the stateless work named both the number and the
  path. A changelog is a historical record, so the entry now reads "ADR-0009
  (…, numbered 0006 at the time)" rather than being quietly rewritten to look
  as though it always said 0009.

Verified: no reference to either old filename remains anywhere in the tree, no
ADR number is used twice, and witan-council's 839 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017oVnpzjRJQVWq9hJGE2Rs7
Review feedback on #253 (Copilot). The renumber missed four citations that say
ADR-0006 and mean the stateless 2026-07-28 protocol era — which now resolves to
the branch-ownership decision instead, i.e. exactly the ambiguity the renumber
existed to remove, just pointing the other way:

  packages/witan-core/witan_core/remote/config.py:47
  packages/witan-core/witan_core/remote/__init__.py:7
  mcp/servers/witan/witan/remote/__init__.py:9
  docker/witan.Dockerfile:152

All four are unambiguous in context — each sits in a sentence about there being
no handshake and no session id — so all four become ADR-0009.

My earlier sweep searched by *filename* and caught only the one bare `ADR-0006`
in `witan/config.py`. Bare numeric citations are the whole problem a duplicated
number causes, so searching for the filename was the wrong instrument.

Re-swept for every remaining `ADR-0004`/`ADR-0006` mention in the tree. All of
them are correct as they stand: each surviving `ADR-0004` is the Keycloak
JWT→actor mapping and each `ADR-0006` is code-graph branch ownership, and both
of those kept their original numbers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017oVnpzjRJQVWq9hJGE2Rs7
Base automatically changed from witan-tool-param-descriptions to main August 19, 2026 17:18
blarghmatey added a commit that referenced this pull request Aug 19, 2026
Review feedback on #253 (Copilot). The renumber missed four citations that say
ADR-0006 and mean the stateless 2026-07-28 protocol era — which now resolves to
the branch-ownership decision instead, i.e. exactly the ambiguity the renumber
existed to remove, just pointing the other way:

  packages/witan-core/witan_core/remote/config.py:47
  packages/witan-core/witan_core/remote/__init__.py:7
  mcp/servers/witan/witan/remote/__init__.py:9
  docker/witan.Dockerfile:152

All four are unambiguous in context — each sits in a sentence about there being
no handshake and no session id — so all four become ADR-0009.

My earlier sweep searched by *filename* and caught only the one bare `ADR-0006`
in `witan/config.py`. Bare numeric citations are the whole problem a duplicated
number causes, so searching for the filename was the wrong instrument.

Re-swept for every remaining `ADR-0004`/`ADR-0006` mention in the tree. All of
them are correct as they stand: each surviving `ADR-0004` is the Keycloak
JWT→actor mapping and each `ADR-0006` is code-graph branch ownership, and both
of those kept their original numbers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017oVnpzjRJQVWq9hJGE2Rs7
@blarghmatey
blarghmatey force-pushed the witan-adr-renumber branch 2 times, most recently from fa4d17d to eaf219c Compare August 19, 2026 19:34
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.

2 participants