docs: use grammar-v2 URNs in CLAUDE.md and help-text examples - #333
Conversation
The CLI has emitted flat grammar-v2 URNs since the urn-compose-v2 change (hrn:mem:<root>:<slug>, hrn:node:<root>:<slug>:<loc…>), and the server and MCP layer both emit v2 too — but CLAUDE.md still listed the four Hadron memories in v1, which is where agents (and humans copying from it) picked the old spelling up. Several help-text examples showed v1 as well. - CLAUDE.md: the four memory refs, the two hadron_get_node calls, and the tasks:review-changes task node are now v2. Verified each resolves live, including a colon-bearing loc (hrn:node:hadronmemory.com:hadron-cli:tasks:review-changes). - CLAUDE.md gained an explicit "emit v2, accept everything" rule, so the next reader knows v1 in a test fixture is deliberate acceptance coverage (#239) rather than drift — and that the spec group's memoryRefV1 is a documented exception, because a fixed-arity flat v2 node URN can't round-trip a compound app-mem memory (<org>::<agent>:app-mem:<slug>). - `access check` help/examples and `memory attach`'s example now show v2; `notFoundMemory` and the under-qualified-resource error name hrn:mem: as canonical while still naming the legacy prefix. Behaviour is unchanged — every one of these is help text, an example, or an error string. The access-check guard already passed any hrn:-prefixed ref through untouched, so v2 resources always worked; confirmed live that hrn:mem:hadronmemory.com:hadron-cli resolves as kind=memory. The under-qualified-resource error deliberately keeps `e.g. hrn:memory:<input>`: it interpolates what the user just typed, which contains "::", so the legacy prefix composes into a valid URN where hrn:mem: would not. Not touched: memoryRefHelp already listed hrn:mem: as canonical, and the v1 test fixtures are the legacy-acceptance coverage. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
There was a problem hiding this comment.
Pull request overview
Updates developer-facing documentation and CLI help/error text to consistently present grammar-v2 URNs (hrn:mem:<root>:<slug>, hrn:node:<root>:<slug>:<loc…>) as canonical, while still documenting legacy v1 spellings as accepted input.
Changes:
- Refreshes
CLAUDE.mdmemory/node URN examples to grammar-v2 and adds an explicit “emit v2, accept everything” rule (including thespecexception rationale). - Updates
access checkhelp text/examples andmemory attachexamples to usehrn:mem:/ v2 node URNs. - Revises
notFoundMemoryand the “under-qualified resource” usage error to namehrn:mem:as canonical andhrn:memory:as legacy.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
CLAUDE.md |
Updates canonical URN examples to grammar-v2 and clarifies v2 emission vs legacy acceptance rules. |
internal/cmd/access/check.go |
Adjusts help text and examples to use hrn:mem: and v2 node URNs, while noting v1 acceptance. |
internal/cmd/access/access.go |
Updates the under-qualified resource guidance to include hrn:mem: as canonical and documents why the legacy prefix may appear in examples. |
internal/cmd/memory/attach.go |
Updates the memory attach example from hrn:memory: to hrn:mem:. |
internal/cmd/memory/memory.go |
Updates the “not found” error string to describe v2 canonical URN plus accepted shorthands and legacy prefix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // The suggested example keeps the legacy hrn:memory: prefix on | ||
| // purpose: it composes correctly with the "::" shorthand the user | ||
| // just typed, whereas the canonical hrn:mem: form uses single | ||
| // colons throughout (hrn:mem:acme.com:kb). | ||
| "%q is not a fully-qualified resource URN — prefix it with its kind "+ |
There was a problem hiding this comment.
Good catch on the single-colon case — fixed in 651abb1. You're right that my "deliberate" comment only covered the :: shorthand; for acme.com:kb the suggestion composed to hrn:memory:acme.com:kb, mixing a v1 prefix with a v2 separator.
memoryURNExample now picks the prefix that matches the separator:
acme.com:kb → hrn:mem:acme.com:kb (canonical)
acme.com::kb → hrn:memory:acme.com::kb (legacy)
One correction to the premise, since it changes why this matters: hrn:memory:acme.com:kb is not actually invalid. I checked against the live server before changing anything, and its decomposer resolves all three spellings to the same memory:
hrn:memory:hadronmemory.com:hadron-cli -> RESOLVES (hrn:mem:hadronmemory.com:hadron-cli)
hrn:mem:hadronmemory.com:hadron-cli -> RESOLVES (hrn:mem:hadronmemory.com:hadron-cli)
hrn:memory:hadronmemory.com::hadron-cli -> RESOLVES (hrn:mem:hadronmemory.com:hadron-cli)
So the old message pointed at something that worked — it just wasn't canonically shaped, and it contradicted the same sentence's claim that hrn:mem: is canonical. Worth fixing for that reason; the comment now says so rather than implying a validity bug. Covered by TestMemoryURNExampleMatchesSeparator, plus a first test file for the package covering normalizeResourceRef's pass-through, bare-id, and rejection paths.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 13565c5eb9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| fully-qualified URN — hrn:mem:…, hrn:node:…, hrn:app:…, or hrn:agent:… | ||
| — or a bare AiServiceConfig id. The legacy hrn:memory:<org>::<slug> | ||
| spelling is still accepted. |
There was a problem hiding this comment.
Update the embedded agentic usage for v2 URNs
After declaring the flat v2 forms canonical here, the separately exposed hadron agentic-usage contract still documents only hrn:memory:<org>::<slug> and the double-colon node form (internal/cmd/agentic/agentic-usage.md:120-126), and its access check section still lists only hrn:memory: (:578-583). Agents using that command rather than Cobra help will therefore continue generating the legacy spelling and are not told that server-emitted flat node URNs are accepted; update the embedded contract alongside these help changes. CLAUDE.mdL63-L63
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Right, and this was the more consequential of the two — fixed in 651abb1.
agentic-usage.md is the file hadron agentic-usage prints, and its own header calls it "the single reference an agent needs to drive the CLI". Leaving it on v1 while declaring v2 canonical in cobra help would have meant agents reading the documented contract keep emitting the legacy spelling and never learn that the server-emitted flat URNs are accepted at all — exactly the loop that put v1 in CLAUDE.md in the first place.
Both places you flagged are updated:
- :120-126 now leads with the emit-v2/accept-everything rule and gives the canonical forms (
hrn:mem:<root>:<slug>,hrn:node:<root>:<slug>:<loc…>), with every legacy spelling still listed as accepted. The node bullet also explains why scheme-less single-colon stays ambiguous while the flat v2 form is not — thehrn:node:prefix is what disambiguates. access checknow listshrn:mem:…alongside the legacy prefix.
Verified in the rendered output:
$ hadron agentic-usage | grep -n 'hrn:mem:|grammar-v2'
120:- **URN grammar: the CLI emits flat grammar-v2, and accepts every spelling.**
122: `hrn:mem:<root>:<slug>` for a memory and `hrn:node:<root>:<slug>:<loc…>` for a
126:- Memory references accept the memory id, the canonical `hrn:mem:<root>:<slug>`
591: — `hrn:mem:…`, `hrn:node:…`, `hrn:app:…`, `hrn:agent:…` (the legacy
…contract Review follow-ups on #333. - The under-qualified-resource error always suggested `hrn:memory:<input>`. I had called that deliberate, but it only holds for the "::" shorthand: for the single-colon form it produced hrn:memory:acme.com:kb, mixing a v1 prefix with a v2 separator. memoryURNExample now picks the prefix that matches the separator the caller used — hrn:mem: for `a:b`, hrn:memory: for `a::b`. Worth recording: Copilot's premise was that the mixed form is invalid. It isn't — the server's decomposer resolved all three of hrn:memory:<org>:<slug>, hrn:mem:<org>:<slug> and hrn:memory:<org>::<slug> to the same memory. So this is about handing back a canonically-SHAPED example, not about validity, and the comment says so. - agentic-usage.md — the embedded contract `hadron agentic-usage` prints — still documented only v1, so an agent reading it (rather than cobra help) would keep emitting the legacy spelling and never learn that server-emitted flat URNs are accepted. It now leads with the emit-v2/accept-everything rule, gives the canonical memory and node forms, and `access check` lists hrn:mem: alongside the legacy prefix. Adds the access package's first test file: memoryURNExample against both separators, and normalizeResourceRef's pass-through / bare-id / rejection paths. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Answers "where is the V1 URN coming from?" — it was CLAUDE.md.
The CLI has emitted flat grammar-v2 URNs since docs/plans/urn-compose-v2.md (
hrn:mem:<root>:<slug>,hrn:node:<root>:<slug>:<loc…>), and both the server and the MCP layer emit v2 as well. But CLAUDE.md still listed the four Hadron memories in v1, which is where agents reading it — and humans copying from it — picked up the old spelling. A few help-text examples showed v1 too.Changed
CLAUDE.md — the four memory refs, the two
hadron_get_nodecalls, and thetasks:review-changestask node. Each verified to resolve live, including a colon-bearing loc:It also gained an explicit "emit v2, accept everything" rule, so the next reader knows two things that are easy to get wrong:
specgroup'smemoryRefV1is a documented exception, not drift: a fixed-arity flat v2 node URN can't round-trip a compound app-mem memory (<org>::<agent>:app-mem:<slug>).Help text —
access check's description and examples,memory attach's example,notFoundMemory, and the under-qualified-resource error now namehrn:mem:as canonical while still naming the legacy prefix.Behaviour is unchanged
Every change is help text, an example, or an error string.
normalizeResourceRefalready passed anyhrn:-prefixed ref through untouched, so v2 resources always worked — the help just never said so. Confirmed live:One deliberate inconsistency worth flagging: the under-qualified-resource error keeps
e.g. hrn:memory:%[1]s. It interpolates the string the user just typed, which contains::— so the legacy prefix composes into a valid URN there, wherehrn:mem:would produce a mixed-separator ref that isn't. Commented in place.Not touched
memoryRefHelpinmemory/memory.goalready listedhrn:mem:<root>:<slug>as canonical withhrn:memory:marked legacy — it was already right.access_cmd_test.go,run_cmd_test.go,spec_commands_test.go.docs/plans/*.md, which are point-in-time design records.memoryRefV1— see the compound-memory blocker above.go test ./...— 16 packages green.make lint— 0 issues.gofmt -l .clean.🤖 Generated with Claude Code