Skip to content

papercuts: undocumented abstract cap, spec edit can't set description, leaked server error on a malformed memory ref #338

Description

@shadowbrush

Three small things hit while refreshing a stale spec abstract (cor:urn:010:01, follow-up to #333). Each is a one-line docs or message fix; grouped rather than filed separately.


1. The 2000-character abstract cap is undocumented — and --dry-run doesn't catch it

spec edit --help says nothing about a length limit, and there's no client-side check: the server is the only guard.

The awkward part is that --dry-run reports success first, so the cap surfaces after you've verified the change:

$ hadron spec edit cor:urn:010:01 -m …::specs --abstract-file /tmp/oversize.txt --dry-run
would update cor:urn:010:01 — URN grammar
  abstract: updated                                   # 2100 chars — looks fine

$ hadron spec edit cor:urn:010:01 -m …::specs --abstract-file /tmp/oversize.txt
hadron: input:3: updateNode Abstract exceeds 2000-character cap (got 2141 chars).
Use a shorter summary or expand 'content' for the long form.

The server's message is good — it's the timing that costs you, since the whole point of --dry-run is to find problems before writing.

Fix: mention the cap in --abstract / --abstract-file flag help, and validate length in --dry-run (and ideally before the write) so it fails at the same point every other usage error does. input:3: is a GraphQL source location leaking through, too — this would be a exitcode.Usage error if checked client-side.


2. spec edit silently doesn't support description

It covers --abstract / --abstract-file and --content / --content-file. A spec node also has a description, which is what spec list and hadron_find_nodes show — and it can go stale in exactly the same way the abstract does (both were stale on cor:urn:010:01).

--help doesn't mention description at all, so the absence reads as an oversight rather than a decision. The workaround is to switch commands mid-task:

hadron spec edit   cor:urn:010:01 -m …::specs --abstract-file new.txt
hadron node update cor:urn:010:01 -m …::specs --description ""

Fix: either add --description / --description-file to spec edit, or say in the long help that description is edited with node update and why. Splitting them may well be deliberate — it just isn't discoverable.


3. A malformed memory ref leaks a raw server error instead of the CLI's own guidance

notFoundMemory gives a well-shaped message, but only for a well-formed but absent ref. A malformed one never reaches it:

$ hadron memory get definitely-not-a-memory
hadron: input:3: memory URN "definitely-not-a-memory" is not fully qualified. Expected a
memory URN with at least 2 hierarchy segments (org::memory, e.g., "acme.com::mmdata").

$ hadron memory get hadronmemory.com::does-not-exist
hadron: no memory found for "hadronmemory.com::does-not-exist" — expected a memory id or a
URN: hrn:mem:<root>:<slug> (canonical), the <root>::<slug> / <root>:<slug> short forms, or
the legacy hrn:memory: prefix

Two problems with the first:

  • it leaks input:3: (a GraphQL source location) into user-facing output
  • it contradicts the CLI's own guidance. "at least 2 hierarchy segments (org::memory)" describes v1 grammar, while the CLI now advertises hrn:mem:<root>:<slug> as canonical (docs: use grammar-v2 URNs in CLAUDE.md and help-text examples #333). A user following that message writes the legacy form.

This also cost me a moment of confusion: probing notFoundMemory with an obviously-bogus ref returned the server's message, so I briefly thought I'd edited unreachable text.

Fix: validate the ref shape client-side in memory get (and the shared resolveMemoryID) before the round-trip, returning notFoundMemory — or a sibling usage error — so both paths give the same, v2-correct guidance.


None of these blocks anything; all three are discoverability rather than behaviour. #3 is the one I'd prioritise, since it actively points users at the legacy URN grammar the rest of the CLI has moved away from.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions