MiCyte

← The wiki

40 — Tools, channels, routines and lenses

BuiltRendered from 40-tools-and-lenses-asbuilt.md in the public repository. Edits belong there.

MiCyte has three registers of things that act on an instance (tools, channels and automation routines) and one registry of lenses that format values for display.

Three registers

RegisterModuleAn entryRefuses
Toolsmicyte/tools/_registry.pyA WorkbenchTool: builds a panel payload for a personAn object with a routine_id or channel_id
Channelsmicyte/channels/__init__.pyA HostedChannel: a GET-only page a participant reaches (91)Tools and routines
Routinesmicyte/automation/An AutomationRoutine: writes or calls because a condition heldAn object with build_panel_payload, route or applies_to_archetype

Registered today: two channels (agnet, convention) and four routines (email_triage, email_verification_request, email_verification_sync, site_analytics_refresh). No routine runs on a schedule; each is declared, refused until granted, and run by hand.

The tool contract

A tool satisfies the runtime-checkable Protocol WorkbenchTool in micyte/tools/_contract.py:

MemberMeaning
tool_id, label, summaryIdentity and palette text
routeThe route the palette dispatches; tools open on /portal/system/tools/workbench-ui?tools=<id>
applies_to_archetype, applies_to_source_kindWhen the tool is offered for the document in focus. Both empty means the tool is opened by address against the instance (a hub or an instrument)
build_panel_payload(*, authority_db_file, sandbox_id, document_id, datum_address)Returns the payload the workbench renders

Optional attributes, read with defaults:

AttributeMeaning
writesA tuple of DeclaredWrite(document_kind, action). The write policy judges each write against these
requiresA ToolRequirement: documents that must be held (documents, documents_any), fields the sandbox anchor must express, and sources rows read from other sandboxes. Install provisions them. A requirement is not a permission
iconThe rail sprite symbol
wants_surface_queryReceive the request's query arguments as extra_query
wants_host_contextReceive host_context: private_dir and port, a callable that returns a bound adapter for a port_id or None

Tools register themselves by calling register(...) at import; micyte/tools/__init__.py imports each module. all_tools() returns them sorted by id.

The registry today

MiCyte registers 45 tools: 20 declare writes, 24 are opened by address, 23 belong to a package and 22 belong to none. The host application registers its own tools beside them. Ask the registry rather than a list:

from micyte.tools import all_tools, declared_writes
[t.tool_id for t in all_tools()]

fnd_app/tests/architecture/test_tool_registry_shape.py pins the registry as an exact set. Every registered tool must declare a write or name what it derives; a tool that only renders a document's own values is drawn by a viewscope instead (41).

A tool belongs to at most one package (packages_by_tool raises on a shared claim). A hub composes other tools as tabs; 46 lists the packages.

Eligibility

Two questions decide whether a tool is shown:

  • Can this sandbox run it? instance_can_use (46).
  • Does it apply to the selection? recognize_applicable_tools in micyte/state_machine/portal_shell/tool_eligibility.py builds the document's archetype set from its metadata and from every row reached along the selected datum's hyphae chain, and matches it against applies_to_archetype; it also matches the source kind against applies_to_source_kind. test_palette_eligibility_purity.py keeps this function free of I/O.

The palette runtime serves GET /portal/api/tools/eligible (for a selected document) and GET /portal/api/visualizers/for-sandbox (for a sandbox, ranked by how many documents each tool can render). An empty applies_to_* matches everything; no document context returns every tool.

Tools are not bound to a specific hyphae value or to a family's root datum; that binding is not built (60).

Lenses

A lens is a stateless codec (Lens in micyte/state_machine/lens/base.py) with decode, encode and validate_display.

Lens idEffect
identityPass-through; the fallback
trimmed_stringStrips whitespace
samras_titleDecodes a SAMRAS-encoded title
email_addressLowercases and checks @ placement
secret_referenceShows a vault reference, never the value
numeric_hyphenValidates hyphenated digit groups (SAMRAS and HOPS addresses)
fiat_centsShows a fiat magnitude as currency: 450 as $4.50
binary_textDecodes a printable binary string to ASCII; otherwise shows {n} bits

DatumLensRegistry (registry.py) chooses a lens by recognized family, then overlay kind, then value kind, defaulting to identity. The workbench resolves one lens per row and shows the result as the row's display value; the lens never changes the stored row. A lens can be disabled per instance through POST /portal/api/lenses/toggle; a disabled lens falls back to identity. The panel module for these toggles exists but no surface mounts it (81).

The workbench also has a workbench_lens query mode, interpreted (default) or raw, which switches the column set. It is separate from the lens registry.