6 Commits

Author SHA1 Message Date
calic
318de44cc9 fix(deps): cascade composition 0.4.0 + crafting 0.5.0 pins
Phase J (2026-08-03) bumped lib-core.composition 0.3.0->0.4.0 and
lib-core.crafting 0.3.0->0.5.0, but only vagrant-skeleton and
lib-core.crafting themselves were updated. Dependent manifests kept the
old pins, so dep-fetcher saw disagreeing pins on the same lib and
refused to start both spine-prototype (ENGINE_ERR_LIB_DEP_MISSING,
rc=19) and vagrant-skeleton ("dep check failed", conflict on
lib-core.composition + lib-core.crafting).

Unify all pins on the on-disk versions. No code changes required:
composition 0.4.0 is purely additive (the quality/condition loud-error
was removed; no signature changed), and crafting-display only consumes
crafting.can_craft + crafting.list_recipes, both still present, and
never referenced the `form` field retired by ADR-0055.

README "Requires:" lines synced to match the manifests (Gate 3).

milestone-check.sh: GREEN (build, ctest, smoke, devwrap-ci,
test-all-modules + anomaly scan). vagrant-skeleton headless run clean
at 60 CI frames.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 11:27:20 +02:00
Calic
1368c0aebd docs: CR-4 — README Scope/create-Signatur auf v0.2.0 + panel-dep v0.1.1->v0.4.0 synct
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 14:32:35 +00:00
Calic
c725ffd3bc fix: nil-guard in _invoke_context_menu + README English
- _invoke_context_menu now early-returns if locale_factory()
  returns nil mid-frame, symmetric with build_rows. Prevents the
  race where a workbench destroyed between render and right-click
  would propagate nil locale into ctx_inner and crash craft.
- README v0.2.0 sections (M.create + action-callback) translated
  from Denglisch to English for consistency with the rest of the
  file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 19:53:00 +02:00
Calic
31e51ee8b7 feat: v0.2.0 locale_factory replaces single container
M.create now accepts either a function (locale_factory, called per
frame to resolve the current crafting locale) or a bare entity-handle
(wrapped internally as a constant factory for v0.1 bw-compat). The
factory's return value is forwarded to crafting.can_craft as the new
multi-source / single-sink locale, enabling dynamic topologies
(adjacent-container sets that change as the actor moves) without
recreating the widget.

Action callbacks now receive ctx_inner with both `locale` (the
currently-resolved locale, either the Form-2 table or the Form-1 bare
handle) and `container` as a bw-compat alias pointing at locale.sink
(Form-2) or the handle itself (Form-1). Existing v0.1 callers using
ctx.container keep working unchanged.

New backdoor _test_get_locale exposes the locale_factory's current
return value. README documents both Form-1 and Form-2 with examples
plus the updated callback contract.

Depends on lib-core.crafting v0.2.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 19:43:49 +02:00
Calic
b42b707a8e fix: align widget contract with lib-core.panel API
The widget contract was implemented as render(theme, x, y, w, h) and
handle_input(input_state, theme, x, y, w, h), but lib-core.panel
dispatches widgets as render(ctx) and handle_input(ctx, event) where
ctx = {bounds = {x,y,w,h}, theme, is_focused} and event carries
{kind, x, y, button} for clicks or {kind, dy} for wheel.

The mismatch would have surfaced as a crash on the first render frame
(theme.row_height read on a nil first arg) and as a permanently dead
right-click (no field matched input_state.right_clicked because the
real signature passes an event table). Both bugs were masked by the
existing tests, which exercise the public registration surface but
never drove render or handle_input headless.

Changes:
- widget.render and widget.handle_input now match panel's contract.
- _render_widget consumes ctx.bounds + ctx.theme; reads packed-RGBA
  text colours directly instead of falling back to synthetic float
  arrays (panel theme stores 0xRRGGBBAA integers).
- _handle_input_widget dispatches on event.kind == "click" and
  event.button == "right", iterating _render_rows for hit-testing.
- draw_text now passes theme.font_size_body so the engine receives
  the full (text, x, y, size, color) signature.
- Side-effect requires for lib-core.inventory-list and
  lib-core.composition replace the unused-local sentinels, dropping
  the underscore-shadowing.
- _invoke_context_menu trusts mx/my as preconditions and no longer
  defends with `or 0` defaults — the entry-point guards nil.

README documents the widget contract explicitly and captures four
v0.2 hardening notes (is_known cache, WARN rate-limit, empty-action
diagnostic, defensive nil-guard) so the deferral is traceable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 13:36:29 +02:00
Calic
eb8f72bcbd feat: lib-core.crafting-display v0.1.0 — Recipe Panel-Widget
UI layer for recipe-based crafting. Reads recipes from
lib-core.crafting, renders the known-subset as a vertical row-list
inside a panel managed by lib-core.panel, and dispatches right-click
context-menu actions registered by the consuming module.

Surface:
  create(container_entity, opts) -> widget_def
  register_action(widget, label, callback)
  unregister_action(widget, label)
  set_icon_resolver(widget, fn)
  set_label_resolver(widget, fn)
  set_summary_resolver(widget, fn)

Row-build is rebuilt per render frame from crafting.list_recipes():
  - Visibility gate: recipe.is_known(ctx); errors hide row + emit [WARN]
  - Availability gate: crafting.can_craft(id, container, ctx).ok
    drives row colour (full vs dim text_color).

ctx comes from opts.ctx_factory() — default returns {}; override to
feed actor/skill/faction state into both predicates. label_resolver
defaults to recipe.name or recipe.id; summary_resolver joins input
template-ids with " + " and suffixes "xN" for count>1.

Right-click hit-tests row-rects captured during render, then opens
the menu via panel.show_context_menu(x, y, actions). Action
callbacks receive (recipe_id, {container, close_menu, refresh}).
Registration order is preserved (array-based, not pairs-based) so
context-menu rendering matches registration sequence.

Depends on lib-core.crafting 0.1.0, lib-core.panel 0.1.1,
lib-core.inventory-list 0.1.0, lib-core.composition 0.3.0. The last
two are not called directly but are required as direct deps so
modules consuming this widget satisfy crafting's transitive needs
(engine resolver is per-module non-transitive).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 12:34:32 +02:00