Repository navigation
Declare collection description and show it in the agent's workspace context - #3464
Conversation
Pragmatic Code Review — PR #3464Review Type: Initial Review (no prior reviews or comments on the PR) SummaryThe change does what the issue asks: One defect should be fixed before merge: a non-string description makes the new query panic on every agent turn. The rest are improvements. How I checked the blocking finding: by reading Requirements Check
Node type sequence. No undeclared key, no Code Review Findings1. 🔴 Critical — a non-string description panics the workspace-context query📁 "SELECT content, json_extract(properties, '$.collection.description') \
FROM node WHERE node_type = 'collection' ORDER BY content ASC",
...
collections.push((row.get(0)?, row.get(1)?));
Result: one bad write on one collection panics context assembly on every agent turn for that database, until someone corrects the value. Recommendation: make the read total. Either select only text values ( Principle: user data must not be able to panic a read path; validate at the boundary or read defensively. 2. 🟡 Important — "a taken name is refused" does not hold after a rename, and the docs now promise it📁
The id-only check predates this PR in Recommendation: in Principle: documented behaviour should match the invariant the code enforces. 3. 🟡 Important — the
|
malibio
left a comment
There was a problem hiding this comment.
Automated pragmatic-code-review: REQUEST CHANGES (posted as a comment — GitHub blocks self-approval). Full findings in the review comment above.
Address-review summary (commit ee96229)Addressed
Skipped
Still open: acceptance criterion 7's
|
Pragmatic Code Review — PR #3464Review Type: Re-Review (commit Previous Review Summary
Consumers of the changed error text: none break. The daemon maps the variant to Tests I ran, all passing: core lib Requirements Check
Code Review FindingsNo critical or important problems. Nothing in the new commit breaks a CLAUDE.md rule: no compatibility code, no issue numbers in comments, no lint suppression, no new literal A. 🟢 Suggestion — the name check does not trim, the id does📁
Recommendation: pass Principle: two checks that guard one invariant should normalize the input the same way. B. 🟢 Suggestion — the name check is ASCII-only for case, so it misses a renamed collection with a non-ASCII capital📁 The lookup lowercases the argument in Rust (Unicode) and the column with SQLite's Recommendation: out of scope to fix here. If it is worth closing, compare a normalized name computed in Rust on both sides (a stored normalized column, or fetch candidates and compare in Rust). Otherwise leave it. C. 🟢 Suggestion — the first name of a renamed collection can never be used again📁 The comment is accurate: after Recommendation: accept it for this PR. The D. 🟢 Suggestion — the name check matches only the literal
|
malibio
left a comment
There was a problem hiding this comment.
Automated pragmatic-code-review (re-review): APPROVE (posted as a comment — GitHub blocks self-approval). Full findings in the review comment above.
Address-review summary, round 2 (commit 56a44bf)Addressed
Skipped
Still open: the |
56a44bf to
7b1fcce
Compare
Pragmatic Code Review — PR #3464Review Type: Re-Review (post-rebase), head How this was checkedBy reading only. A live-model eval is running on this machine, so I ran no cargo, nextest, The range-diff shows what the rebase changed relative to the approved commits:
Previous Review SummaryItems whose status the rebase changed:
Nothing else from the two earlier reviews changed status. The six questions, answered from the code
Code Review FindingsNo critical problems. No new problem in the conflict resolution. No rule in the node-type sequence's reviewer list is broken: no undeclared key, no literal 1. 🟡 Important — the PR description describes the codebase before the rebase📁 PR description ("What changed" → Schema; "Notes for review" → "Not in this PR, by choice") Three statements are no longer true on current main:
Recommendation: edit the description before merge. Say that main declares the field and this PR pins it with a test, drop the "not in the codebase yet" sentence, and say that the registry gives Principle: the squash-merge message is the durable record of the change, and the node-type sequence asks the PR description to state the type's layers accurately. Established by reading, not by running code. 2. 🟢 Suggestion — a subtype collection is now listed, and no test says so📁 After the rebase the listing covers subtypes, and a subtype's inherited description is in the Recommendation: add one assertion to that test: the listing equals Principle: test the behaviour a change introduces at the surface that consumes it. Established by reading, plus a 3. Nit — the bucket key is a string literal in product code📁
Established by reading. Outside this PR
RecommendationAPPROVE The conflict resolutions are correct and lose nothing from main, and |
malibio
left a comment
There was a problem hiding this comment.
Automated pragmatic-code-review (post-rebase re-review): APPROVE (posted as a comment — GitHub blocks self-approval). Full findings in the review comment above.
89681d8 to
68e6f9f
Compare
Address-review summary, round 3 (post-rebase, head 68e6f9f)Addressed
Skipped
Rebased once more onto main (two unrelated commits, no conflicts). Acceptance criterion 7 ( No re-review needed: one test assertion and a description edit. |
…ontext (closes #3421) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ion's name, name the existing collection in the error - The workspace-context query reads a description only when it is text; a stored number or boolean panicked the driver on every agent turn. - new_collection_id also checks the name, since a renamed collection keeps the id of its first name. - AlreadyExists names the collection in the way and its id. - Test the deterministic id for a subtype of collection. - Say the description budget is counted in bytes. Skipped: renaming the listing query to return a struct, the per-create chain lookup (needed to cover subtypes), and bounding description length in SQL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… text for create and rename - new_collection_id trims the name before the lookup, as the id does, so a padded spelling of a renamed collection's name is refused. - rename_collection's refusal names the existing collection and its id, like the create's. - State the two checks and their order in one place. Skipped: SQLite's ASCII-only LOWER in the name lookup (predates this change, also affects rename), and the lookup's literal collection type (matches its sibling queries). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h its description Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68e6f9f to
e2c50cf
Compare
Closes #3421
What changed
A collection's
descriptioncan now be set from the CLI and the agent, and the agent sees it in its workspace context.Node type (node type sequence):
collectionis a concrete core type, category flat, generic wire shape in the registry. Main already declares the field; this PR adds no field, relationship, structural rule or participation rule:descriptioncollection.descriptionDocs: the
collectionsheet incomponents/node-types.mdalready describes the field and where it is shown; no docs change is needed.collectiondeclares exactly one field, an optional textdescription.create_collectionwrites the description into thecollectionbucket explicitly.node_ops::create_node(whatnodespace node create --type collectionand the agent'screate_nodecall) now derives a collection's id from its name, as the collection op and imports do. Before, it minted a random UUID, so the CLI could create a second collection with a taken name. The check goes through the registry (type_is_a), so a subtype ofcollectionis covered.Already exists: collection '<name>' (id <uuid>).rename_collectionuses the same text.WorkspaceContext.collectionscarries name and description. With no descriptions the section is unchanged (COLLECTIONS: a, b). Once any collection has one, it is one collection per line,- name — description; a collection without one stays a bare name. Each description is cut to one line of 80 characters, descriptions together take at most a quarter ofmax_chars(later collections are listed by name), and if the list still doesn't fit the section falls back to the names line. Subtypes ofcollectionare listed too.references/cli.mdteaches--property description=…on a collection, on create and update, and says why.SKILL.mdcarries one sentence: its body had 36 characters left under the 5,000-token limit, so two redundant clauses in the same section were trimmed to make room.Notes for review
properties.description, which the viewer header reads. A wire test pins that.collectionas a generic wire shape, so its description is written through the generic update. No typed struct is added here.--property description=42as a number, and text fields are not type-checked on write) reads as no description in the workspace context. Before the fix it panicked the listing query in the database driver.--property description=null) stores a JSON null, as it does for every type; it reads as no description.LOWER, and the first name of a renamed collection stays taken.Tests
create_node/update_nodeset and change a collection description.node create --type collection --property description=…andnode update --property description=…end to end.properties.description.eval:decisionsbefore and after: posted on #3421.🤖 Generated with Claude Code