hgraph Development
Howard Peter Henson v0.1.0
Publisher description
From the marketplace listing
Author and review hgraph operators, wiring-time graphs, and efficient C++ compute and sink node implementations using the project's established contracts and validation practices.
Language: English · Automatically detected from descriptions.
Publisher keywords
Search terms declared by the publisher.
Matches for “programming”
Exact text from the indicated source. A mention alone does not establish support for your task.
Publisher keywords · listing
hgraph cpp functional-reactive-programming agent-skills
Files & skills
File archives
Skill instructions
hgraph-compute-sink-node12.8 KB
---
name: hgraph-compute-sink-node
description: Implement or review C++ hgraph compute nodes, sink nodes, algorithms, and concrete operator-node specializations. Use when adding or changing a static node `eval`, lifecycle hooks, local or recordable state, REF usage, incremental or windowed algorithms, input-type branching, operator strategy selection or overload registration, type-erased node strategy, node naming, complexity documentation, or native/Python behavioral tests for a compute or sink node.
---
# HGraph Compute and Sink Nodes
Build C++-first nodes whose per-tick path is small, whose lifecycle and state
semantics are explicit, and whose names and tests fit the operator system.
## Start from the existing contract
1. Read the current repository's `AGENTS.md` and the relevant operator
definition, implementation, registration, and tests before editing.
2. Establish whether the task targets hgraph core or a downstream extension:
- In the hgraph core checkout, read the applicable parts of
`docs/source/user_guide/cpp/authoring_nodes.rst` and use
`tests/cpp/test_static_node.cpp` as the compact executable reference for
lifecycle hooks, `State`, and `RecordableState`.
- In a downstream project, use that project's extension layout and tests,
plus the public hgraph headers and documentation for its pinned hgraph
version. Do not assume the hgraph core source tree is present.
3. Classify the work before choosing a type:
- Use a compute node for time-series input plus an output.
- Use a sink node for time-series input and a side effect with no output.
- Implement an operator specialization when the behavior belongs to an
existing abstract operator or valid implementations may vary by type or
algorithm.
- Introduce a standalone node only when the behavior is not an operator and
cannot be expressed clearly as a graph.
Keep static node implementation structs empty. Put instance data in the
appropriate selector or plan rather than in members.
Keep the node's per-tick implementation logic in `eval`. Extract a helper only
when it is a well-defined operation with its own clear contract or is genuinely
shared by multiple callers. Do not scatter one node's implementation across
single-use helper functions. Keep one-off lifecycle work in `start` and `stop`
as described below.
## Design the hot path first
Treat `eval` as the hot path. Leave only work that depends on the current tick.
- Prefer typed `In`, `Out`, `State`, and `RecordableState` access.
- Avoid schema discovery, registry lookup, overload selection, RTTI, string
construction, parsing, policy selection, and representation selection in
`eval`.
- Avoid avoidable allocation, container growth, reference counting, locking,
and Python conversion in `eval`. Reuse pre-sized storage when the algorithm
requires scratch space.
- Resolve wiring-time scalar policies to a concrete overload or plan. Do not
branch on a policy string every tick.
- Read each input view only as often as needed. Use modified/delta access when
full-value traversal is unnecessary.
- Emit no output when the contract calls for no tick; do not manufacture an
unchanged value merely to simplify control flow.
If expensive work appears unavoidable, state why, inspect neighboring hot-path
code, and add focused performance evidence for a material regression risk.
## Select input types through operators
Treat an `if`/`else`, `switch`, schema-kind test, RTTI check, or visitor branch
that chooses node behaviour from an input's type as a design signal: stop and
make the alternatives operator overloads. Wiring already knows the concrete
input schemas, so select the implementation once there instead of rediscovering
the type during `start` or on every `eval`.
- If an operator already describes the behaviour, implement and register a
more-specific node or graph overload.
- If no operator exists, introduce an implementation-free operator contract,
then register the concrete implementations under it. Follow
`../hgraph-write-operators/SKILL.md`.
- Keep each node signature as specific as its implementation. Template shared
code where useful, but register the concrete instances that wiring should
choose.
- Use a wiring-time scalar value and overload `requires_` predicate when a
fixed policy selects an implementation. Do not carry that choice into the
hot path.
- Use runtime switching only when the selecting value is itself time-series
data and the contract genuinely permits the implementation choice to change
while the graph runs.
Do not hide semantic type selection inside an erased helper or plan. An erased
ops-table may dispatch representation mechanics at a required abstraction
boundary; it must not replace the operator registry's wiring-time selection of
meaningfully different behaviours.
## Use REF deliberately
Treat `REF` as a semantic indirection with significant memory overhead, not as
the default way to connect nodes. Input bindings to non-`REF` outputs are
lightweight C++ structures.
- Use a normal binding when the consumer only needs to read an output.
- Use `REF` when indirection prevents a value from being copied from an input
to an output. Selection and routing operators such as `if_then` and `route`
are the primary pattern: capture the selected source output and direct that
source instead of copying its current value.
- Use `REF` when dynamic source identity is part of the operator contract.
- Before adding `REF`, state which copy or dynamic binding it avoids and verify
that plain input binding cannot express the behavior.
Do not reject `REF` merely because it is expensive. Use it whenever the
indirection is required, and pay its overhead intentionally.
## Place one-off work in lifecycle hooks
Use `start` for work performed once per node lifetime, including:
- initializing `State`, or seeding `RecordableState` only when it is invalid;
never overwrite recordable state restored for replay;
- initializing sequences, cursors, buffers, or cached plans associated with
that state;
- acquiring run-scoped resources or establishing subscriptions;
- scheduling the initial evaluation when declarative `schedule_on_start` is
insufficient.
Use `stop` to flush, finalize, unsubscribe, or release what `start` acquired.
Keep teardown safe for partial lifecycle progress and follow existing scope
guard patterns where rollback is required.
Request only the selectors each hook needs. When lifecycle-only arguments are
required, use the established explicit `signature_args` pattern rather than
polluting `eval`.
## Choose state by semantics
- Use no state for a pure transformation or side effect.
- Use `State<T>` for private, ephemeral implementation state that does not
participate in record/replay.
- Use `RecordableState<TSchema>` when a tick updates state that affects later
ticks: this is loopback or feedback state and should be observable and
restorable by record/replay.
- Do not combine `State` and `RecordableState` in one static node.
- Keep recordable state structured and typed. Update only the fields modified
by the current tick.
Do not replace semantic loopback state with an opaque cache merely because the
cache is easier to implement.
## Implement algorithms incrementally
Prefer an incremental algorithm that consumes the current tick or delta and
updates only the sufficient statistics needed for the result. Do not retain an
entire history or window in private state when an online formulation exists.
Minimal sufficient statistics are algorithmic state; they are preferable to
capturing the input history.
- Put incremental state that affects later ticks in `RecordableState`.
- When an exact result intrinsically requires the window contents, use `TSW`
as the semantic window rather than copying the window into private state.
Exact median is the standard example.
- Do not maintain a private duplicate of a `TSW` merely to simplify the
implementation.
- Test an incremental implementation against a simple full-recomputation
reference over multiple ticks, including removals and boundary conditions.
Document algorithmic cost beside the implementation and public operator:
- state the worst-case or amortized time cost per tick;
- state retained-memory cost;
- for `TSW`, express both costs in terms of window size `W` and document the
supported window semantics.
## Exploit concrete C++ types
Use type erasure at boundaries that genuinely need to accept independently
realized types. Once wiring or plan construction selects a concrete strategy,
make the per-tick implementation typed.
- Template an implementation when its scalar or time-series types vary, and
use those template parameters to remove runtime conversion and dispatch.
- Use the operator registry to choose a concrete typed overload instead of
inspecting `TSTypeKind`, scalar metadata, or a schema in the node.
- Select erased representation operations once from immutable wiring or plan
metadata, then dispatch through the installed ops table.
- Follow the repository passive ops-table plus explicit erased-ownership
pattern for a reusable erased contract. Do not add a facade `std::variant`
or scatter strategy branches through semantic node code.
- Preserve native C++ authoring as the primary path. Adapt Python values and
callables to the same node rather than implementing separate Python runtime
semantics.
## Name operator implementations consistently
Name a concrete operator node from the operator plus a concise specialization
suffix, using lower snake case.
- If the operator name ends in `_`, append the suffix directly:
`add_` + `float` becomes `add_float`.
- Otherwise insert `_` as the separator:
`debug_print` + `tsb` becomes `debug_print_tsb`.
- Describe the specialization by the distinguishing type, shape, policy, or
direction. Avoid generic suffixes such as `impl` when a precise name exists.
- Apply the same rule to the implementation type and any explicit diagnostic
`name` unless a nearby registration convention requires a different label.
Keep the abstract operator in its operator header, the concrete node under the
existing `impl` boundary, and register it through the neighboring operator
registration mechanism.
Use the operator as the public abstraction whenever implementation selection
may vary by type or algorithm. Keep concrete node choices behind overload
resolution or the operator's wiring contract.
When an operator offers meaningful algorithmic trade-offs, expose a strongly
typed enum as a wiring-time scalar policy:
- Give each enum value a name that describes the accepted property or risk.
- Document accuracy, overflow, numerical stability, time, and memory trade-offs
that differ between values.
- Select the concrete overload or immutable plan before execution; do not
switch on the enum in `eval`.
- Use a graph-level switch only when the policy is genuinely time-varying.
For example, average may offer sum divided by count, with overflow risk, and an
online recurrence based on the previous average, count, and next value, with
different floating-point accuracy behavior. Test every exposed strategy.
## Document standalone nodes
For a node that is not an operator, add documentation beside its public or
implementation declaration that states:
- why a primitive node is required instead of a graph or existing operator;
- its input activation and validity behavior;
- its output or side-effect contract;
- its lifecycle and state semantics;
- any intentional hot-path cost or external-resource behavior.
Add user-facing documentation when the standalone node is public. Do not add
domain-specific behavior to core merely because the algorithm is generic.
## Test through public wiring
1. Add native C++ behavior coverage using a concrete minimal graph and
`eval_node`. Cover sink side effects without driving runtime internals
directly.
2. Cover multiple ticks for stateful nodes, including initialization, update,
no-tick behavior, and teardown where relevant.
3. Prove recordable loopback state through its public recordable-state behavior.
4. Add equivalent Python authoring/bridge coverage for every Python-visible
behavior; keep the semantic implementation in C++.
5. Test invalid input, passive/active behavior, and lifecycle failure in
proportion to the risk.
6. Run focused tests while iterating, then every acceptance gate required by
the current repository `AGENTS.md`. Add an installed-SDK consumer check for
public-header changes and cross-platform validation for large runtime or
type-erasure changes.
Before handing off, review the final diff specifically for work that can move
out of `eval`, unnecessary `REF`, retained history that can become incremental,
state that should be recordable, undocumented per-tick or window cost, policy
branches that should select an overload, per-tick erased dispatch that can
become typed, and names that do not identify their operator specialization.
Referenced files: 1
hgraph-write-graphs7.24 KB
---
name: hgraph-write-graphs
description: Implement or review composable C++ hgraph graphs and Python `@graph` functions. Use when adding or changing graph composition, wiring-time type or scalar decisions, graph overloads and polymorphism, `GlobalState` or `LOGGER` graph injection, conditional wiring, graph documentation, or native/Python graph behavior tests.
---
# Write HGraph Graphs
Build behavior by composing small typed nodes and graphs at wiring time. Prefer
graphs as the ordinary unit of reuse; reserve new nodes for genuine runtime
primitives or demonstrated performance needs.
## Start from the existing contract
1. Read the current repository's `AGENTS.md`, the relevant operator and graph
code, and nearby tests before editing.
2. Establish whether the task targets hgraph core or a downstream extension:
- In the hgraph core checkout, read the applicable parts of
`docs/source/user_guide/cpp/authoring_graphs.rst`,
`docs/source/user_guide/python/tutorial/graph.rst`, and
`docs/source/developer_guide/graph_wiring.rst`.
- In a downstream project, use that project's graph conventions and tests,
plus the public hgraph documentation for its pinned hgraph version. Do
not assume the hgraph core source tree is present.
3. Identify the existing nodes, operators and graphs that already provide the
required primitives. Compose them before creating a new primitive.
4. Preserve equivalent first-class C++ wiring and Python authoring behavior
for every public cross-language feature.
Apply all repository documentation and type-system rules. A graph is not a
shortcut around signature validation, generic resolution or operator dispatch.
## Prefer a graph to a node
Start new behavior as a graph. A graph combines small, purpose-specific,
efficient and well-tested nodes into more complicated behavior, reducing the
new runtime code and validation surface.
Create a node only when the behavior requires a new per-tick primitive, side
effect, lifecycle service, runtime state transition, or a measured performance
improvement that composition cannot provide. Document that reason. Apply
`$hgraph-compute-sink-node` when implementing or reviewing the node.
Keep the trade-off explicit:
- Prefer composition and reuse by default.
- Measure before replacing a clear graph with a fused node for performance.
- Keep a justified fused node narrow and expose it through the same operator or
graph contract where practical.
## Keep graph work at wiring time
A C++ graph's `compose` method and a Python `@graph` function execute once while
the graph is wired. Graphs flatten into their nodes and do not exist as runtime
evaluation objects.
Keep the graph's wiring implementation in `compose` or the decorated graph
function. Extract a helper only when it is a well-defined operation with its
own clear contract or is genuinely shared by multiple callers. Do not scatter
one graph's composition across single-use helper functions.
- Treat ports as typed wiring handles, never as current values.
- Inspect scalars, resolved types and wiring metadata only to choose topology.
- Do not retain runtime state or expect the graph body to run on a tick.
- Do not perform runtime side effects in a graph body.
- Move lifecycle and tick-dependent behavior into nodes.
The topology, overloads, bindings and policies selected by the graph are fixed
when graph composition returns.
## Compose for reuse and polymorphism
Use graphs as the primary workers for reusable behavior:
- Factor repeated compositions into small graphs with precise typed
signatures.
- Compose graphs from other graphs; do not duplicate their internal nodes.
- Use generic graph signatures for type-safe reuse across compatible schemas.
- Use operator overloads when callers need polymorphic selection by type,
shape or wiring-time algorithm policy.
- Use higher-order graph parameters when the caller should supply behavior.
- Keep wiring-time policy selection out of every node's `eval` path.
Prefer an operator contract over exposing one concrete graph when multiple
valid graph or node implementations may exist.
## Limit graph injectables
Graphs support only `GlobalState` and `LOGGER` as injectables.
- In Python, declare either injectable with a `None` default and never supply
it from a graph call.
- Use `GlobalState` for graph-scoped wiring configuration and values that seed
the built graph. Runtime reads or writes still belong in nodes.
- Use `LOGGER` to report wiring choices, resolved types and selected policies.
It is the logger selected for graph wiring, not a per-tick node view.
- In C++, access the equivalent services through `Wiring::global_state()` and
`Wiring::logger()`.
- Do not inject `STATE`, `RECORDABLE_STATE`, `SCHEDULER`, `CLOCK`,
`EvaluationEngineApi`, `Traits` or `NODE` into a graph. Put behavior that
needs a runtime service in a node.
Use a node `LoggerView` or the logging operator for runtime values. A graph
logger cannot observe ticks because the graph body has already finished.
## Make wiring choices explicit
A graph may inspect resolved type information, scalar configuration and wiring
metadata; perform ordinary conditional logic; select overloads; and log why it
made a choice.
- Base Python type decisions on resolved annotations, `AUTO_RESOLVE` values and
supported metadata APIs.
- Base C++ decisions on concrete template types and wiring-time scalar values.
- Log a material type, policy or implementation choice when it helps explain
the built topology.
- Use runtime control-flow operators such as selection, switching, mapping and
mesh when a time-series value must change behavior after wiring.
Never read a time-series value to choose topology. Never imply that a logged
wiring choice can change later in the run.
## Preserve documentation and type rules
- Give every graph a complete input and output signature.
- Keep generic variables linked consistently across inputs, outputs and scalar
resolution parameters.
- Return the declared time-series shape and preserve the established `REF`,
dereference and structural binding rules.
- Keep scalar policies at wiring time and use enums where several named
trade-offs are supported.
- Document public behavior, wiring-time choices, supported types, error cases
and any measured reason for choosing a node over a graph.
- Update authoritative operator and type documentation with the implementation.
## Test through public wiring
1. Test graph behavior through `eval_node` with concrete public signatures.
2. Add equivalent native C++ and Python coverage for Python-visible behavior.
3. Cover every conditional wiring branch, generic type specialization and
exposed algorithm policy.
4. Assert invalid types and unsupported graph injectables fail during wiring.
5. Test wiring-time logging without confusing it with runtime log output.
6. Prefer behavior assertions over internal node-count or index assumptions,
except when topology itself is the contract.
7. Run focused tests while iterating, then every acceptance gate required by
the current repository `AGENTS.md`.
Before handing off, review the final diff for runtime work left in the graph
body, a new node that could be a composition, time-series-dependent wiring,
unsupported injectables, unresolved type variables, and wiring decisions that
are not documented or tested.
Referenced files: 1
hgraph-write-operators9.98 KB
---
name: hgraph-write-operators
description: Define or review hgraph operator contracts and overload families in C++ and Python. Use when adding a C++ operator marker or Python `@operator`, replacing input-type or wiring-policy branches with overload selection, implementing node or graph overloads, registering C++ or Python candidates, designing defaults/resolvers/requires predicates, diagnosing overload ranking or ambiguity, generating the Python operator surface, or testing operator dispatch and cross-language parity.
---
# HGraph Operator Authoring
Define a public function-like contract once, then let wiring select the most
specific registered implementation for the concrete argument schemas and
fixed scalar choices. Keep the contract pure and the implementations typed.
## Read the existing family first
1. Read the current repository's `AGENTS.md`. In the hgraph core checkout,
also read `docs/source/developer_guide/operators.rst`; in a downstream
project, use its extension conventions and the public operator
documentation for the pinned hgraph version instead.
2. Inspect the nearest operator marker, implementation header, registration
translation unit, C++ tests, and Python compatibility tests.
3. For a compute or sink implementation, also follow
`../hgraph-compute-sink-node/SKILL.md`. For a graph overload, follow
`../hgraph-write-graphs/SKILL.md`.
4. Inspect `include/hgraph/types/operator_dispatch.h` only when the task needs
defaults, `requires_`, output resolution, variadic arguments, or dispatch
diagnostics beyond the established neighbouring pattern.
## Define a pure function contract
Treat an operator as a function interface. It names one logical operation,
describes the general call shape, and documents behaviour shared by every
implementation. It is not executable. "Pure contract" means
implementation-free here; a sink operator may still contractually describe a
side effect.
- Give the marker only its name and abstract signature. Do not put `eval`,
`start`, `stop`, `compose`, state, or implementation decisions on it.
- Document the semantic result, tick/validity expectations, errors, wiring-time
policies, and argument meanings. Describe the supported family without
promising one representation or algorithm unless that is part of the
contract.
- Choose parameter names deliberately; implementations should preserve those
names and their roles so named calls remain coherent.
- Use broad base type contracts in the marker. Use independent type variables
when operands or output may differ; repeat a variable only when equality of
those types is part of the public contract.
- Match the public Python operator name exactly, including any trailing
underscore.
For example:
```cpp
/** Normalize values according to the wiring-time mode.
@param ts Values to normalize.
@param mode Supported normalization contract.
@return Values in the overload-selected output shape. */
struct normalize : Operator<"normalize",
In<"ts", TsVar<"S">>,
Scalar<"mode", NormalizeMode>,
Out<TsVar<"O">>>
{
};
```
The marker signature is documentary. Candidate matching uses each
implementation's own signature, which is what permits a single operator to
cover concrete, generic, and heterogeneous types through node and graph
realizations. Output-producing and sink contracts remain distinct call shapes.
## Use overloads instead of type switches
When implementation code starts branching on an input type, schema kind,
scalar type, or fixed policy, move that choice into operator resolution. Wiring
knows these facts and should select the implementation once.
- Add an overload to the existing operator when the behaviour already has a
contract.
- Introduce a new operator when no contract exists for the functionality; do
not leave a standalone type-switching node as the public abstraction.
- Use a graph-level dynamic switch only when the selector is time-series data
and the choice must legitimately change during execution.
- Keep representation-only dispatch inside an established erased ops-table;
do not use erasure to conceal semantic implementation selection.
## Refine the contract in implementations
Make every candidate more precise than, or otherwise compatible with, the
general function contract:
- Preserve the contract's base argument order, names, and semantic roles.
- Refine `TsVar`/`ScalarVar` inputs to concrete schemas, constrained variables,
aligned repeated variables, or structural shapes that the implementation
actually supports.
- Refine the output independently when the result differs from the inputs.
- Use a compute or sink node overload for primitive runtime work. Keep its
logic in `eval` and its lifecycle work in `start`/`stop`.
- Use a graph overload when the implementation composes existing operations
at wiring time.
- Use a concrete scalar type to refine by policy type. Use a context-aware
`requires_` predicate to refine by a wiring-time scalar value, and use
`resolve_default_types` only to bind output variables that inputs cannot
determine. Keep candidates mutually exclusive or deliberately ranked.
An implementation may add positional parameters or keyword arguments not
shown by the abstract signature because dispatch is driven by candidate call
shapes. Use that freedom sparingly: overload-specific parameters are difficult
to discover. Prefer a common contract parameter, a separate operator, or a
strongly typed policy enum. When an extra is justified, document it in the
operator's public documentation and exercise the named call in both C++ and
Python tests.
## Register C++ overloads explicitly
Follow the standard family layout:
1. Put the abstract marker and its documentation in
`include/hgraph/lib/std/operators/<family>.h`.
2. Put concrete node/graph implementations under the corresponding `impl`
boundary, normally
`include/hgraph/lib/std/operators/impl/<family>_impl.h`.
3. Register node candidates in the family registration translation unit with:
```cpp
register_overload<normalize, normalize_float>();
register_overload<normalize, normalize_tsd>();
```
4. Register graph candidates with:
```cpp
register_graph_overload<normalize, normalize_tsl_map>();
```
5. Add a new family registration function to
`register_standard_operators()` when introducing a standard family. An
extension should expose and call its own explicit registration entry point.
When a new standard family is genuinely needed, also add its definition header
to `operators/operators.h`, its implementation header to
`impl/operators_impl.h`, and its registration translation unit to the CMake
source list. Prefer adding an operator to the nearest existing family over
creating a one-operator family.
Never register from a static initializer. Registries are reset between tests,
and candidate patterns borrow interned type metadata. Register standard types
first, then overloads, once per registry lifetime. Tests that need standard
operators call `stdlib::register_standard_operators()` before wiring.
## Connect the same registry to Python
Keep C++ as the source of truth for core runtime semantics. The Python surface
must adapt to the same native operator registry rather than implement a second
dispatcher or a parallel runtime operation.
For a public native operator:
- Register the C++ overloads under the exact public name. The Python module
calls `register_standard_operators()` at initialization, and registered names
become lazy `hgraph.<name>` callables through `operator_function`.
- Preserve enough marker documentation and overload metadata for generated
signatures and docstrings.
- Regenerate the public catalogue, Python typing declarations, runtime
docstrings, and API inventory with:
```sh
.venv/bin/python tools/api_inventory.py
```
- Add Python tests through the public operator name to prove authoring and
bridge parity with the native C++ test.
For a Python-authored operator or extension overload, declare the contract and
attach implementations with the normal decorators:
```python
@operator
def normalize(ts: TIME_SERIES_TYPE, mode: NormalizeMode) -> OUT: ...
@compute_node(overloads=normalize)
def normalize_float(ts: TS[float], mode: NormalizeMode) -> TS[float]:
...
@graph(overloads=normalize)
def normalize_tsd(ts: TSD[K, TS[float]], mode: NormalizeMode) -> TSD[K, TS[float]]:
...
```
`overloads=` registers each Python candidate through
`register_python_overload`; the native matcher still owns argument
normalisation, type binding, ranking, `requires`, and selection. Use decorator
`resolvers=` and `requires=` for wiring-time facts. Do not write Python-side
type dispatch. When the behaviour belongs in core, provide the first-class C++
path and equivalent C++ tests rather than leaving it as a Python-only runtime
implementation.
## Test the contract and selection
Test through the operator, not by wiring the concrete candidate directly.
1. Register the intended overload family after test registry reset.
2. Use native `eval_node<Op>` or a minimal concrete graph to prove every
Python-visible behaviour at the same level.
3. Cover the generic fallback and each more-specific winner. Include mixed
types, structural shapes, scalar-value policies, defaults, invalid inputs,
and output-only resolution as applicable.
4. Add no-match and ambiguity coverage when adding ranking-sensitive
candidates. An accidental tie is a design error, not a registration-order
selection rule.
5. Add equivalent Python `eval_node` coverage through the public operator.
6. Regenerate and check the API inventory for a public native operator.
7. Run the focused tests, then the acceptance gates required by `AGENTS.md`.
Before handing off, confirm that the marker contains no implementation, no
node chooses behaviour by inspecting an input type, every overload is
explicitly registered, overload-specific parameters are justified and
documented, Python uses the same registry name, and tests prove which candidate
wins rather than only the candidate's isolated arithmetic.
Referenced files: 1
Package details
Publisher declarations from the archived package. These are separate from our research and the live service's terms.
- Package license
- MIT
- Package author
- Howard Henson
- Keywords
- See publisher keywords
Declared capabilities
- Read
- Write
Package observed Oct 3, 2026.
Technical details
- First seen
- Sep 30, 2026 · 22:02 UTC
- Last seen
- Oct 3, 2026 · 12:00 UTC
- Collection status
- Collected
plugins_6a85a5758d408191bbc948af18f557a2
Download plugin data (JSON)Before you connect hgraph Development
How do I connect it?
Open the publisher's marketplace listing to check current availability and follow its connection instructions. This directory does not install plugins. Check the requested access and any account requirements before connecting.
Check marketplace availability ↗
Does it require paid access?
We have not established the pricing or subscription requirements for this plugin. An absent price does not mean free access.
Compare researched pricing and access models →
How can I evaluate it?
Check the declared skills and available files, then try a small task whose result you can verify. Our archived descriptions and instructions establish publisher claims, not tested runtime quality. Review sources and coverage limits.