Skip to content

chore: combined working stack — inspector consolidation + mode taxonomy/bundling/content-negotiation [DO NOT REVIEW]#327

Draft
castor-agent wants to merge 48 commits into
mainfrom
claude/combined
Draft

chore: combined working stack — inspector consolidation + mode taxonomy/bundling/content-negotiation [DO NOT REVIEW]#327
castor-agent wants to merge 48 commits into
mainfrom
claude/combined

Conversation

@castor-agent
Copy link
Copy Markdown
Collaborator

@castor-agent castor-agent commented May 20, 2026

Stack

This is a working branch combining two PRs under review. Do not review this PR directly.

Review each PR individually. This branch exists solely as a working surface on top of both.

Entity management (Inspector)

Latest commit on this branch (3cf552e8e): entity-agnostic Inspector management for the entities list page.

  • Backend: snapshot_filters on /entities/query (eq, in, gt, lt, gte, lte, contains); sort_by accepts snapshot.<field>
  • Inspector: field filter bar, snapshot-field sort, row selection + bulk actions (set field, delete, status), inline cell edit via batch_correct, create-entity dialog, board/kanban view with drag-and-drop (@dnd-kit), saved views (localStorage per entity type)

Merge plan

  1. Merge Mode taxonomy + inspector bundling + content-negotiation unification #323 into main
  2. Rebase chore: consolidate neotoma-inspector into neotoma (subtree import) #324 onto updated main → merge
  3. This branch will be fast-forwarded or closed

Conflict resolution

The only conflict was the inspector submodule pointer from #323 vs the real inspector/ directory from #324. Resolved by keeping the subtree content and removing the displaced pointer.

Test plan

  • npm run dev (3080) — entities list: filters, sort, bulk bar, inline edit, create dialog
  • Board view: group-by field, drag between columns updates snapshot field
  • Saved views: save/load filter + sort + column + view mode per entity type

markmhendrickson and others added 30 commits April 7, 2026 18:15
- Vite + React + TypeScript admin for entities, sources, timeline, graph
- API client for Neotoma HTTP endpoints
- Radix UI components and Tailwind styling
- Dev scripts for local/prod API targeting

Made-with: Cursor
Expand the inspector into a fuller operator UI with agent attribution, recent activity and conversations, richer entity and source detail views, and shared components for browsing provenance-heavy records.

Also update local inspector DX by wiring the matching API environment and keeping lint focused on source files instead of generated build output.
Publish the inspector as a static GitHub Pages shell so users can point it at their own Neotoma API, while documenting the HTTPS and CORS requirements that make that setup work.

Also add the project-base routing and SPA fallback needed for deep links to work on Pages.
GitHub Pages project URLs use /<repo>/ as the asset base, but a root
custom domain (e.g. inspector.neotoma.io) serves assets at /. Read
optional Actions variable VITE_PUBLIC_BASE_PATH; when unset, keep
format('/{repo}/') for default github.io deployments.
Hosted static builds (e.g. GitHub Pages) no longer default the API base to
loopback. Production bundles without VITE_NEOTOMA_API_URL use an empty
default; isApiUrlConfigured gates TanStack queries until Settings saves a
URL. requireApiBase guards fetch helpers; dashboard shows a Settings CTA.

Add optional sandbox mode (VITE_NEOTOMA_SANDBOX_UI): banner, /sandbox page,
session + sandbox API helpers, Settings lock/hide destructive UI when enabled.

Also: header API target copy when unset; search/sidebar/source queries
respect API readiness.
Preconfigure GitHub Pages builds for inspector.neotoma.io to use
https://sandbox.neotoma.io as the production API base unless a repo
variable overrides it for another hosted deployment.
Adapt the Inspector for the bundled-at-/inspector architecture:
- Remove DEFAULT_SANDBOX_BASE_URL (same-origin, relative URLs only)
- Remove fallbackApiBase from consumeSandboxSessionHandoff
- Use relative /sandbox/session/* URLs in banner and redeem
- Delete deploy-pages.yml (no standalone GitHub Pages deployment)
- Update README for bundled architecture
Add the inspector UI, API clients, and shared components needed by the agent compliance and attribution work staged in the parent repo.
Add feedback admin unlock, sync, and local store UI needed for the v0.11.0 inspector release work.
Add inspector screens and API clients for issues, access policies, schema admission grants, and agent/entity attribution views. Replace the feedback-admin UI with the issue-oriented workflow so the bundled inspector matches the current Neotoma issue pipeline.
Use a const-typed verified-via config so badge lookups stay type-safe while preserving the existing fallback behavior for unknown verification sources.
Add peer and subscription API clients, hooks, navigation entries, and pages so the bundled Inspector can display sync peer and substrate subscription state.

Enhance dashboard, entity detail, issue detail, access policy, and timeline views to surface nervous-system entities, external actor attribution, and local development proxy behavior used by the host Neotoma branch.
Pin dev:vite, build:vite, build:watch, and preview scripts to
vite.config.ts so CI contract test passes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add home/docs/FAQ routes, bundled docs navigation, and pinned primitive
shortcuts in the sidebar. Refactor header search, entity detail segments,
source preview, and relationship panels. Collapse the sidebar More section
by default with a persisted toggle and auto-expand on active routes.
…-2026-05-003)

Wires the new GET /conversations/:id/turn-index endpoint into the conversation
detail page. Adds:

- ConversationTurnIndex, ConversationTurnIndexTurn, ConversationTurnEntityRef
  types in src/types/api.ts mirroring the backend response schema.
- getConversationTurnIndex API client in api/endpoints/recent_conversations.
- useConversationTurnIndex React Query hook.
- TurnTimelineSidebar component — scrollable list of turns with role icon,
  stored/retrieved/issue counts, and deep-link to #msg-N anchor.
- TurnAnchorSections component — one card per turn with deterministic anchor
  IDs (#msg-N, #stored-N, #retrieved-N, #issues-N). Issue consent card renders
  inline under #issues-N when the turn has pending issues.

The conversation detail page now renders a two-column layout (sidebar + anchor
sections) when the turn-index loads; falls back to the existing flat message
list when the index errors (e.g. before the backend ships).

Depends on the GET /conversations/:id/turn-index endpoint shipped in the main
repo via FU-2026-05-003 backend PR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…026-05-003)

Dismissible banner shown on the conversation page that tells users about the
inline turn-summary widget available in MCP clients that load
`@neotoma/ext-apps-widget-host`. Renders above the turn anchor sections.

Dismissal persists in localStorage (`neotoma_inspector_widget_host_prompt_dismissed`)
so the banner does not nag once acknowledged.

The prompt is purely informational — the widget host is loaded by MCP clients
themselves, not from inside Inspector. The prompt surfaces that the option
exists.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ntent (#267)

Add Intent-triggered task creation rule to [TASKS & COMMITMENTS] section of
MCP instructions. When user messages contain trigger phrases ("I need to",
"remind me", "follow up", "I should", "don't let me forget", "make sure I",
"I have to", "I want to", "I must", "don't forget", "remember to"), agents
MUST create a task entity with entity_type: "task" and status: "pending" in
the user-phase store (Step 2) before composing the reply. Explicit FORBIDDEN
clauses prevent deferring task creation or skipping it when trigger phrases
are present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… creation (#253)

Add [RELATIONSHIP CREATION] section to the MCP fenced instruction block
with five rules:
- Pre-store candidate discovery: check for logically related entities
  before completing a store; FORBIDDEN to skip this consideration
- Relationship-in-same-store: prefer the store relationships array over
  separate create_relationship calls; use create_relationships only as
  follow-up when target id was unknown at store time
- Canonical relationship examples: 8 typed REFERS_TO patterns (person→org,
  task→conversation, activity→source conversation, issue→plan/spec,
  note→subject, event→place, task→person, entity→source artifact)
- retrieve_related_entities for traversal guidance
- Relationship direction convention for REFERS_TO and PART_OF

Add pointer-only entry in cli_agent_instructions.md per canonical-first
sync rules (no duplicating full instruction body).

Update Design rationale section inventory to include [RELATIONSHIP CREATION].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a Usage page to the Inspector that surfaces aggregate statistics
about the user's own Neotoma activity, computed from local data only.

- Add UsageStats interface to src/types/api.ts
- Add GET /usage API endpoint wrapper in src/api/endpoints/usage.ts
- Add useUsage() TanStack Query hook in src/hooks/use_usage.ts
- Add UsagePage with 4 stat cards, entities-by-type bar chart, and
  observations-by-source bar chart in src/pages/usage.tsx
- Wire UsagePage route in App.tsx
- Add Usage nav item (TrendingUp icon) to sidebar analytics section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extract graph layout utilities, tighten entity ID handling in graph explorer,
and extend humanize/relationship panel grouping for relationship views.
Per-turn anchor sections, turn timeline sidebar, and ext-apps widget host
mode discovery. Resolve api.ts conflict by keeping UsageStats and turn-index types.
When the diff-size gate evaluates to substantial=false, a new step posts
a PR comment stating the file/line count and the thresholds that would
trigger a review, plus the @claude review escape hatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…wcase

Add dedicated entity history and design showcase routes, shared timeline
components (world-time events, layer headers, history sections), and refine
graph explorer, entity detail, and timeline pages for clearer navigation.
Update inspector to entity history, timeline layers, and design showcase.
Refine lexical search so multi-word titles containing registered type names
still match (e.g. plan titles ending in "Strategy"). Add shadcn audit/rules
and FU-2026-05-003 plan. Docs hierarchy Playwright spec lands separately
once GET /docs?format=json is wired.
Adds `src/services/skills/seed_schema.ts` — an idempotent boot-time
schema seeder for the `skill` entity type, following the same pattern
as plans and issues. Wires `seedSkillSchema()` into `actions.ts` so the
global skill schema (fields: name, description, triggers, content, slug,
user_invocable, enabled, version, supported_harnesses, harness_config,
synced_at) is guaranteed to exist on every server start, surviving fresh
DB installs without requiring manual MCP calls.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds `docs/developer/skills_guide.md` covering skill entity storage,
MCP/CLI retrieval, mirror-to-disk layout, slash-command palette
activation via `user_invocable`, and the full field reference.

Also adds the Feature guides section to `getting_started.md` (in line
with PR #314) with skills listed alongside plans, issues, mirror, and
subscriptions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…versation (#258)

Add scrape_chatgpt_workout skill to .claude/skills/ with explicit
provenance wiring between stored workout_session entities and the
source conversation entity.

Key additions over the pre-fix state:
- Phase 3 preamble requires conversation_entity_id to be set before the
  store loop; directs agent to run Phase 4 first on a fresh capture
- Step 3.2 explicitly collects every entity_id from store responses into
  session_entity_ids for use in Step 3.3
- Step 3.3 calls create_relationships to batch-create REFERS_TO edges
  from each workout_session entity_id to conversation_entity_id
- Step 4.2 directs agent to store the returned entity_id as
  conversation_entity_id for use in Step 3.3
- Constraints section adds two MUST rules: run Phase 4 before Phase 3
  on fresh capture; collect all session entity_ids before
  create_relationships

Closes #258

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…on unregistered entity_type (#269)

When update_schema_incremental is called for an entity_type with no registered or
code-defined schema, it previously threw an opaque McpError(-32603). Now returns a
structured non-throwing response with error_code ERR_NO_SCHEMA_FOR_ENTITY_TYPE,
no_schema_for_entity_type: true, and an actionable hint pointing to register_schema
and analyze_schema_candidates.

When the entity_type has an existing schema that lacks canonical_name_fields and
identity_opt_out (R2 enforcement), the R2 error is caught and surfaced as a structured
response with error_code ERR_SCHEMA_MISSING_IDENTITY_CONFIG and a hint to call
register_schema with a full schema_definition including canonical_name_fields.

Adds regression tests covering both cold-start cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…248)

- Add docs/subsystems/entity_field_semantics.md: canonical definitions for
  source (system slug), source_url (URL), source_ref (upstream external ID),
  and data_source (audit string); includes canonical slug table and forbidden
  examples
- Update docs/developer/mcp/instructions.md fenced block: add source field
  rule — slug only, never a URL or person name, use source_url/source_ref for
  those; link to entity_field_semantics.md
- Update docs/subsystems/record_types.md: tighten dataset source description
  to reference entity_field_semantics.md
- Update src/services/schema_definitions.ts: add inline comments on income,
  note, and agent_task source field declarations pointing to canonical doc
- Update docs/doc_dependencies.yaml: register entity_field_semantics.md as
  upstream for schema_definitions.ts, instructions.md, and record_types.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
castor-agent and others added 13 commits May 20, 2026 09:14
#195)

On first issue-filing encounter with no reporting_mode configured, the
agent now checks for a stored `preference` entity with
`title: "issue_filing_consent"` before prompting. If a preference
entity exists, its value (`always`/`ask`/`never`) drives the resolved
mode without re-asking the user. If no entity exists, the agent asks
once with clearer always/ask/never framing, then persists the choice
two ways: as a `preference` entity (for cross-session memory) and via
`neotoma issues config --mode` (for the runtime config flag).

The QA-driven issue filing section is updated to reference the same
preference-entity lookup flow rather than the old prompt-only path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…an ent_b4958d038bd41e8694fe0aef)

Implements all 6 phases of the sandbox-mode / topology-aware auth plan,
closing the v0.11.1 advisory regression class for self-hosted deployments
that lack explicit auth configuration.

Phase 1 — Resolver + install fingerprint (sandbox_mode.ts)
- `resolveSandboxMode()`: pure-function resolver classifies boot topology
  into authenticated | local_sandbox | hosted_sandbox | refuse.
- `resolveRefusePolicy()`: reads NEOTOMA_REFUSE_MODE (default "warn").
- `getOrCreateInstallFingerprint()`: stable 16-hex ID stored at
  <dataDir>/.install_fingerprint; drives per-install sandbox principal.
- `sandboxPrincipalIdFromFingerprint()`: deterministic UUID-shaped user ID.

Phase 2 — Wire resolver into actions.ts startup
- Boot-time call to `resolveSandboxMode()` + `emitSandboxBootBanner()`.
- `refuse` mode: logs advisory banner with three remediation options;
  `NEOTOMA_REFUSE_MODE=enforce` makes it fatal (default: warn, no breakage
  for existing self-hosters).
- Precedence: auth configured → authenticated; NEOTOMA_SANDBOX_MODE=1 →
  hosted_sandbox; loopback bind + non-prod → local_sandbox; else → refuse.

Phase 3 — ensureLocalSandboxUser() (local_auth.ts)
- Materialises a deterministic per-install `local_sandbox` user on every
  boot; replaces the silent all-zeros LOCAL_DEV_USER_ID fallback so two
  co-located installs resolve to distinct principals.

Phase 4 — sandbox_allowed column in protected_routes_manifest.json
- sync_protected_routes_manifest.js emits `sandbox_allowed` for every
  route: auth-required routes default to "none", open routes to
  "hosted_ok".
- auth_topology_matrix.test.ts: two new sanity tests assert every route
  declares a valid sandbox_allowed value and that auth-required routes
  default to "none".
- Manifest regenerated (108 routes, all with sandbox_allowed).

Phase 5 — UI auth bootstrap (already shipped; plan confirmed no-op delta)

Phase 6 — Advisory cross-reference
- docs/security/advisories/2026-05-11-inspector-auth-bypass.md extended
  with remediation guidance and links to the new resolver.

Also: fix typo in package.json copy:env script (colpy → copy).
Also: add "root": true to .eslintrc.json to stop ESLint traversing up
  to the main repo's eslintrc when running in a git worktree.

Tests: 38 pass, 1 skipped (HTTP probe, off by default).
Type-check: 0 errors. Format: clean. Lint: 0 errors.
Security manifest: in sync (108 routes).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…eshIndicator

PageShell was refactored to use `meta`/`actions` instead of `headerRight`.
QueryRefreshIndicator no longer accepts a `query` prop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PageShell.headerRight → PageShell.meta; QueryRefreshIndicator.query prop removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rride NEOTOMA_DATA_DIR

Previously hydrateDataDirFromUserEnvConfig() ran first, setting
NEOTOMA_DATA_DIR from ~/.config/neotoma/.env before the project .env
was loaded. dotenv override:false then had no effect.

Swap order: load project .env with override:true first, then call
hydrateDataDirFromUserEnvConfig() which already bails if the var is set.
A worktree .env with NEOTOMA_DATA_DIR now wins over the user global config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…incipal

When resolveSandboxMode() returns local_sandbox at boot, set the module-level
_localSandboxActive flag and provision the per-install fingerprinted principal
via ensureLocalSandboxUser(). Both auth middleware paths (local storage fast
path and encryption-off fallback) now check the flag and stamp the sandbox
principal instead of the shared nil-UUID LOCAL_DEV_USER_ID.

This closes the silent fallback that made every local unauthenticated request
resolve to 00000000-0000-0000-0000-000000000000, causing all browsers and
installs on the same machine to share a single user. Each install now gets
a distinct, stable principal derived from its data dir's install fingerprint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inspector-side support for serving the SPA at the server root via Accept
dispatch (parent repo plan ent_1f176dbbe9a39e6bbad27f1f).

- api/client.ts: every fetch now declares Accept. request() sets
  application/json; getText() declares text/markdown,text/plain,*/*;
  getBlob() declares application/octet-stream,*/*. Prevents the SPA
  shell from accidentally being returned to API calls once the same
  URL serves both surfaces.
- components/layout/sandbox_banner.tsx: explicit Accept on the two
  /sandbox/session/* fetches for consistency with the invariant.
- components/layout/sidebar_user_footer.tsx: render the mode badge for
  every non-`local` mode (was: only `local_sandbox`). Destructive
  variant for `refuse` so the v0.11.1 advisory state is visible.
- types/api.ts: ServerMode enum (`local` | `production` | `local_sandbox`
  | `hosted_sandbox` | `refuse`); UserInfo.sandbox_mode typed as
  ServerMode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ation

Three feature units in dependency order. All complete; stored as plan
entities in Neotoma (ent_6e2080f7f2a961e49876c718, ent_c1d65039242aa2a920d805c7,
ent_1f176dbbe9a39e6bbad27f1f).

## Mode taxonomy (ent_6e2080f7f2a961e49876c718)

Split the legacy `authenticated` verdict so installed-end-user instances
have a distinct mode from hosted multi-tenant. Adds a NEOTOMA_FORCE_MODE
dev override (honored only outside production; hard-rejected at boot in
production with exit 1).

- resolveSandboxMode() returns local | production | local_sandbox |
  hosted_sandbox | refuse. `local` is the new default verdict for the
  installed end-user app. `production` is reserved for hosted
  multi-tenant.
- resolveForceMode() helper reads NEOTOMA_FORCE_MODE; null on
  unrecognized values (typo-safe).
- getResolvedServerMode() exposes the boot-time verdict. /me now
  surfaces the resolved mode unconditionally.
- Tests: resolver expanded from 22 to 29 cases.

## Inspector bundling (ent_c1d65039242aa2a920d805c7)

npm run build now chains build:inspector so end users get a working
bundled inspector by default. Originally planned to mount inspector at
/; discovered that API route names overlap with Inspector client
routes by design. Solved via content negotiation in the next FU.

## Content-negotiation unification (ent_1f176dbbe9a39e6bbad27f1f)

Inspector and REST API share the same URL namespace, dispatched on
Accept. Browsers get the SPA shell; agents/curl/fetch with
Accept: application/json get the existing API unchanged.

- acceptPrefersHtml(accept) parses Accept with quality factors.
  Wildcard and missing-header default to JSON, preserving the agent
  contract.
- isApiOnlyPath(pathname) deny-list for /me, /server-info,
  /sandbox/session, /.well-known/*, /api/*, /mcp/*, /oauth/*,
  /sync/*, /admin/*. Never serve HTML.
- installInspectorSpaFallback registered last. GET/HEAD only;
  mutations never dispatched. Vary: Accept on every HTML response.
- installInspectorRootStaticAssets serves /assets/* and /favicon.svg
  at server root with fallthrough.
- installInspectorLegacyRedirect defined, not yet invoked. Staged
  for future cutover.
- build_inspector.js default VITE_PUBLIC_BASE_PATH=/. Asset URLs now
  at /assets/* (was /inspector/assets/*).
- Inspector api/client.ts (submodule): every fetch declares Accept.
- Legacy /inspector/* mount stays active for back-compat.

## Tests

- Resolver: 29 cases pass.
- Inspector bundled mount: 33 cases pass.
- New inspector_content_negotiation.test.ts: 20 cases.
- Security topology matrix: 18 pass, 1 pre-existing skip.
- Total in touched suites: 100/101 passing.
- Type-check clean. Lint: 0 errors in touched files.

## Not in this PR

- Hosted-sandbox funnel UX (ent_adb92fee6b3c0cfd171a6e0b) — unblocked,
  4-6 week effort, deferred.
- neotoma_user entity type (ent_8d0ec258955475a701f902f7) — independent.
- API namespace migration (ent_462837191284c8b21450ba70) — superseded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the [submodule "inspector"] entry from .gitmodules and the
inspector/ submodule registration. Next commit reimports the inspector
source as a regular subtree, preserving history. See plan
ent_96dbd62a85216fe0bbf76276.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
git-subtree-dir: inspector
git-subtree-mainline: 7b2024d
git-subtree-split: a4dc87b
Follow-up to the subtree import (previous commit). Updates references
that point at the standalone neotoma-inspector repo to instead point
at inspector/ in this repo.

- scripts/build_inspector.js: error message no longer suggests
  `git submodule update --init inspector`; inspector source is now
  part of the repo.
- docs/plans/neotoma-harness-plan.md,
  docs/plans/neotoma-harness-landing-page-net-plan.md: parenthetical
  refers to `inspector/` in this repo with archive note.
- docs/testing/ROUTE_COVERAGE_MATRIX.md,
  docs/testing/WHY_PARTIAL_ROUTE_COVERAGE.md: 2026-04-15 notes updated
  to point at the consolidated location.
- frontend/src/components/illustrations/InspectorPreviewIllustration.tsx:
  external CTA URL now points at the inspector directory in this repo.

Plan: ent_96dbd62a85216fe0bbf76276

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…g/content-negotiation (#323)

Working stack of both PRs — do not review directly; review #323 and #324 individually.
Resolves submodule vs subtree conflict: real inspector/ directory from #324 wins;
displaced submodule pointer from #323 removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@castor-agent
Copy link
Copy Markdown
Collaborator Author

/create_pr skill audit

Automated audit against the /create_pr skill (Neotoma plan ent_8cde942847555a83253dfe5b), which defines the standard PR description structure (Problems / Solutions / UX improvements / Documentation / Test plan / Breaking changes), the pre-PR checklist from .claude/rules/change_guardrails_rules.md, and the functional-change documentation gate (docs entry + docs/site/site_doc_manifest.yaml + docs server surfacing).

Verdict: does not fully meet standards. Gaps below; recommended changes follow each item.

Findings

  • Title is 116 chars (>70 limit).
  • Missing required sections: Problems, Solutions, UX improvements, Documentation, Test plan, Breaking changes.
  • Breaking changes section MUST be present, even for non-breaking PRs (write No breaking changes.).
  • No Related section and no Fixes #N / Closes #N reference — link the plan and/or issue(s) so the PR closes them on merge.
  • Missing the 🤖 Generated with [Claude Code](https://claude.com/claude-code) attribution footer from the skill template.

Recommended changes

Update the PR description to match the skill template exactly:

## Problems
- <Concrete pain point or gap.>

## Solutions
- <Concrete change made.>

## UX improvements
- <User-visible behavior change, or `No user-visible change.`>

## Documentation
- <docs/... path(s) added or updated; parameters/outputs/examples/error modes covered.>
- <`docs/site/site_doc_manifest.yaml` entry added/updated; docs service tests pass.>
- <Or: `No functional change; no user-facing docs required.`>

## Test plan
- [ ] `npm run type-check`
- [ ] `npm test`
- [ ] `npm test -- src/services/docs` (if docs changed)
- [ ] Manual verification: <steps>

## Breaking changes
No breaking changes.

## Related
- Plan: <Neotoma plan entity_id or docs/ path>
- Issue(s): <#N>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Functional surfaces detected from the diff: MCP. Per the skill, the Documentation section must point at a real docs/...md path covering parameters, outputs, at least one example, and error modes, and the doc must be listed in docs/site/site_doc_manifest.yaml so it is surfaced by the docs server and docs site.

Posted by /create_pr skill audit run. See .claude/skills/create_pr/SKILL.md for the full template.

markmhendrickson and others added 5 commits May 21, 2026 11:35
…iring

Add /design marketing-pattern showcase, navigation skeletons with AbortSignal
across API hooks, snapshot_display wiring on entity detail, pinned-primitive
icons, and header search improvements (entity id navigation, cancellable
suggestions). Consolidates May 20 Cursor session work on
feat/fu-2026-05-003-inspector-turn-anchors.
Add conversation_message and other high-confidence type mappings so list
and detail surfaces use consistent icons instead of generic fallbacks.
Expose richer server metadata for Inspector settings and route local HTML root requests to the Inspector SPA while preserving hosted sandbox landing behavior.
Catalog was stale after new test files were added by this branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ctions, and inline editing

- Add snapshot_filters to entity query API: field-level filtering with
  eq/in/gt/lt/gte/lte/contains operators; sort by arbitrary snapshot.*
  fields (e.g. snapshot.status, snapshot.priority)
- Backend: extend EntitiesQueryRequestBaseSchema, queryEntities(), and
  /entities/query handler to accept and apply snapshotFilters
- Inspector entities page: field filter bar, board/kanban view grouped
  by snapshot field, bulk-action bar (select-all, per-row checkboxes),
  inline cell editing, create-entity dialog, and saved views
- New shared components: BulkActionBar, CreateEntityDialog,
  EntityBoardView, EntityFieldFilterBar, InlineEditCell
- New lib: saved_views (localStorage-backed view persistence)
- DataTable: expose row-selection state and column-level edit callbacks

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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