本文へ移動
cccskills
無料GitHub で公開

board-items

Putting a platform feature on the Board (/board) as an Add-menu item with its real component and full agent surface. Use when adding a feature, record type or 'X on the board', or editing features/board/items/** or a tile body.

インストール方法を見る

含まれるファイル(2)

  • SKILL.md10.3 KB
  • evals.md13.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

board-items — a feature on the Board, for real

The Board (/board, features/board/) is the person's own canvas and is meant to become the ONE UI: they drop in anything the platform supports and do their actual work there. Two laws decide whether an item is done:

  1. The tile IS the feature. Its body is the feature's canonical component — the same core the feature's own page renders, with every option, button and mode. A look-alike ("a simple note box", "just the preview") is a defect, however clean it looks. Arman: "if they can't do their actual work, the entire thing breaks."
  2. An agent can do in the tile everything a PERSON can do on the feature's page. The item declares the feature's own surface (values, write targets, client tools) and mounts it for the tile's record. A record item without its full surface is a defect, and so is a gap the page's surface already had (e.g. an agent can't read or edit a document's body): closing it is part of this task.

Mechanics live in features/board/FEATURE.md. Read it once.

The contract — features/board/items/types.ts

A BoardItemType registered in features/board/items/catalog.ts (through work-items.tsx, feature-items.tsx, content-items.tsx, data-items.tsx, or a new <area>-items.tsx you add to the catalog) appears in every board's Add menu, Start panel and agent tools with no other change.

FieldWhat it must be
key, label, icon, group, defaultSizeRegistry key (= source.entity for records); singular noun; Lucide icon (domain icons from components/icons/domain-icons.ts); size that fits the real component
matches(source)source.kind === "entity" && source.entity === key for records
BodyThe feature's canonical component for ONE record — never a new renderer
surface{ name, Host? } for every record item; { none: reason } ONLY for board-only content (label, web page)
startNewOne entry or a list (startNewEntries() reads both). Each is create — synchronous, returns the item to place NOW; the body creates the record through the feature's canonical create path (with the organization gate) on the person's FIRST ACTION (a Create click, or the first words typed), never in a mount effect (a remount or a removed tile would leave stray records; NoteItemBody only starts a client-side draft on mount) — or a Picker (e.g. chat's "Chat with an agent" uses the one agent picker)
bringInA picker built from the feature's canonical picker; most already exist in features/resource-manager/resource-picker/ (Documents, Notes, Tables, Tasks, Files…)
hrefThe record's page — no dead ends
commentsREQUIRED. entityComments(token) for a record item (its own thread, the same one its page shows); null for board-only content, whose door then posts on the Board and says so. every-tile-has-one-comment-door.test.ts fails without it
sleepsOpt-in, and only after the type's remount-safety case passes (see "Sleeping tiles" below)
KeepOptional. Mounted for as long as the tile is on the Board, outside the part that sleeps: what must outlive the body (a chat holds its live run and keeps the tile awake while replying)
guestSafeSet only for board-only content or a meeting's own parts: a meeting guest with no account may add it

The saved form is a REFERENCE ({ kind: "entity", entity, id, meta? }, board/document.ts), never a copy of the record. id is null until the record exists; meta.seed carries pasted text for a record not created yet. A body changes what the tile refers to only through onSource.

Recipe — adding a feature

  1. Find the canonical component. Walk the feature's route down to the component that renders one record with all its controls (for notes: NoteContentEditor + NoteMetadataBar, not the inner NoteEditorCore). Leave out only the app's own navigation (sidebars, tabs of OTHER records, back buttons). Done when every control on the feature's page for that record exists in the tile.
  2. Find the feature's surface. features/surfaces/manifests/*.manifest.ts: its surfaceName, values, writeTargets, clientTools, and WHERE the feature's page mounts SurfaceRuntimeProvider.
    • Mounted inside the canonical component → surface: { name }, no Host.
    • Mounted at page level → extract a record-scoped host component, use it on the page AND as the item's Host (one component, two consumers — never a board-only copy).
    • No surface, or one with no write targets / tools for what the page can do → author or extend it with the surface-authoring skill (a new surface is registered server-side in ui.ui_surface, or every send beside it fails 422). Done when the manifest covers every read and every action the page offers.
    • Declare briefValues (1-5 values that say WHICH record this is and its state at a glance: a note's title + first line, a table's name + row count, a task's status + due date). They are the basics agents see for every item that is not live. Without them the first declared values are used — often ids, which tell an agent nothing. surface-declare.ts checks the names.
  3. Write the item in the matching *-items.tsx, with startNew / bringIn / href.
  4. Fit the plane. Tiles sit in a zoomed, transformed world: position: fixed and components that assume the viewport (WindowPanel) break there; portals and popovers must still open usably. Test at the item's defaultSize and zoomed out. Fix by the component's own props or a portal container — never by forking its UI. A fix that belongs in an @ai-matrx/* package is made in the package (THE SAME-SESSION LAW).
  5. Prove it in the browser with real data (docs/official/browser-testing.md): add one of each (new and brought in), do one real task in the tile, see the change on the feature's own page. Select the tile and confirm exactly ONE registration of its surface, scoped to that record. Then, with a DIFFERENT tile live, ask the Board agent to change your item: it must find it in board_items (with its basics), read it with board_open_item, and change it with board_item_act (through the approval card where the target asks first) — in one turn.
  6. Record it: features/board/FEATURE.md; the feature's FEATURE.md notes its board item and shared host.

Laws a new type must also meet

  • A record is on a Board once. recordKeyOf (board/document.ts) keys every reference; a second tile of the same record on one Board is refused. A tile that shows one PART of a record (meta.part) is its own key. Add a case for a new source kind.
  • Sleeping tiles (the remount law). A tile an unneeded Board freezes or discards must wake with every effect re-run and nothing reloaded or reset. A type may set sleeps: true only when its remount-safety case passes; __tests__/remount-ledger.test.ts fails otherwise, and the ledger (cases.ts) is the one list of which types sleep and which laws each passes. Never list sleepers in prose.
  • Until your feature is a native item, it is a Page tile. items/page-items.tsx puts ANY page of the app on a Board (the page runs in the tile; agents see it by title only). That is the stopgap, never the finish: the native item replaces it, and the item's href must be a real page.
  • A tile error stays in its tile. Every tile sits in its own error boundary; never catch around the tile body to hide a failure.

How the Board keeps surfaces honest

  • ../aidream/apps/shared/chat/src/surfaces/runtime/SurfaceRuntimeContext.tsx SurfaceActivity: everything under active={false} registers nothing. The board wraps every tile; only the LIVE tile (selected, being worked in, or focused) registers its surface globally. So your component may register its surface unconditionally — never add your own "am I on a board?" switch.
  • Every tile ALSO registers into its own capture (SurfaceActivity capture), live or not. That is how an agent reaches any item in the same turn, in two requests:
    1. The board's board_items value (always in context) lists every item: id, title, kind, surface, and a dormant item's basics (its briefValues). The LIVE tile's full surface is already in context through the surface chain.
    2. board_open_item(id) returns that item's values, write targets and client tools, and selects it; board_item_act(id, target+value | tool+input) applies one through the ONE writeback / client-tool runtime, approval card included. So an item whose surface is registered by its Body or Host is fully reachable with no board code. Never write per-item agent tools on the board. features/board/tools/item-surfaces.ts.
  • board_read gives positions, excerpts, each tile's surface and live_tile_id; board_focus makes a tile live (shows it to the person).
  • A component that registers a side door outside the surface runtime (like custom fields' registerCustomFieldsDoor) must check useSurfaceDormant() so dormant copies are not offered.

Red flags — stop

  • "The full component is too big for a tile — I'll render a lighter version." → Render the canonical component; fix what breaks in the plane.
  • "The page's surface is page-level, so the tile gets none for now." → Extract the record-scoped host; that IS the task.
  • "I'll set surface: { none } until the surface exists." → none is for board-only content only.
  • "Agents can't do that on the page either, so it's a separate follow-up." → The page's gap is this gap. Extend the feature's surface (surface-authoring) as part of the item.
  • "I'll create the record when the tile mounts, guarded against double-mount." → Create on the person's first action; mounting is not intent.
  • "Agents can already move and arrange the tile, that's enough." → Arranging is the board's job; the item's job is the feature's own reads and writes.
  • "I'll add a board tool so agents can edit my item." → Declare it on the feature's surface; the bridge reaches it. A Board-specific tool is a second path that drifts.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Admin debug system wiring for the floating AdminIndicator's live debug data and Copy Full Context. Use when adding debug visibility to a route or feature, wiring useDebugContext or the debug panel, capturing console errors, or enabling the copy-context workflow for a page.

日本語の概要は準備中です。原文の説明を表示しています。

armanisadeghi/ai-matrx32026年10月12日 更新

Compact two-icon Copy / Copy-for-AI controls (components/agent-copy). Use when adding copy buttons to a row, card, list, or record; merging duplicate Copy/JSON/AI controls; continuing the copy rollout; or writing a Copy-for-AI payload. NOT for markdown content actions (use rich-document-actions).

日本語の概要は準備中です。原文の説明を表示しています。

armanisadeghi/ai-matrx32026年10月12日 更新

Disclosing a surface's existing fixed AI jobs in the shell's top Agents menu. Use when a page, panel, overlay, or window already runs a mandate behind a button, assist, automatic action, or mode; when the agent-disclosure guard names a file; or during a surface check.

日本語の概要は準備中です。原文の説明を表示しています。

armanisadeghi/ai-matrx32026年10月12日 更新

The watch-fix-rerun method for making an existing platform agent or automated process efficient and correct: baseline its ledger, run one unit yourself, fix the class behind every wasted call, rerun, record. Use when asked to improve, optimize, watch, or 'make efficient' an agent, a sandbox session, a sync job, or any recurring automated process.

日本語の概要は準備中です。原文の説明を表示しています。

armanisadeghi/ai-matrx32026年10月12日 更新

Redux state for agent execution and firing agent shortcuts. Use when editing features/agents/redux/, building agent UI, creating a conversation, touching assembleRequest or NDJSON stream state, wiring agent-state selectors, adding a per-conversation capability, or triggering a shortcut from a button, menu, or code (useShortcutTrigger, launchAgentExecution).

日本語の概要は準備中です。原文の説明を表示しています。

armanisadeghi/ai-matrx32026年10月12日 更新

The provision for a call site: the exhaustive menu of values that place in the code can realistically produce. Use before creating or fixing a mandate or agent that reasons about more than its own input, when deciding whether an agent can answer at all with what it is sent, or when its output 'looks right' but nobody checked it could be. NOT for building the agent (use create-agent).

日本語の概要は準備中です。原文の説明を表示しています。

armanisadeghi/ai-matrx32026年10月12日 更新

armanisadeghi のスキルをすべて見る

このスキルの問題を報告する