Skip to content

feat(telemetry): per-stage form events joinable on a deterministic form_id — 0.8.0 - #59

Merged
silversurfer562 merged 3 commits into
mainfrom
feat/form-stage-telemetry
Aug 24, 2026
Merged

feat(telemetry): per-stage form events joinable on a deterministic form_id — 0.8.0#59
silversurfer562 merged 3 commits into
mainfrom
feat/form-stage-telemetry

Conversation

@silversurfer562

Copy link
Copy Markdown
Member

Chair-approved 2026-08-24 (route "1 — measure first"). The live log had only two event kinds — form_surface and a payload-less form_submitted — so per-stage latency was not computable.

What's here

  • FormSchema.form_id — telemetry join key. An explicit top-level "form_id" definition key wins (validated [A-Za-z0-9._-] token); otherwise form_from_dict derives a deterministic content hash, so the render call and the collect call — which each re-parse the same dict — land on the same id without the agent threading anything.
  • Stage events (same JSONL file, consent gates, 5 MB rotation):
    • form_build — every successful cast; source is "dict" or "template:<name>", which doubles as the V7 template-adoption signal.
    • form_rendered — from form_to_widget_html; carries duration_ms + html_bytes.
    • form_submitted — now carries form_id (MCP collect handler passes it; zero-arg call stays valid for attune-ai ≤ 14.1.0).
    • form_surface records also carry form_id.
  • stage_latency() — p50/p95 read-back: render cost from duration_ms, user-facing wait as first form_rendered → first form_submitted per id, plus counts and the cast-source mix.
  • Shared _append write path (was triplicated), never-raises contract kept.

Receipts

  • 807 passed (pytest tests -q), including 22 new tests: determinism, explicit/invalid form_id, template-source tagging, the full dict→widget→collect round-trip joining on one id, stage_latency percentiles/malformed-line/stale-submission cases, consent gates, zero-arg compat.
  • Changed-module coverage: form_events.py 96%, bridge.py 98%, widget.py 100%.
  • Version 0.8.0 synced across pyproject + plugin + marketplace manifests (test_version_sync.py green).

Companion attune-ai PR (passes form_id at its collect site, compat-shimmed for 0.7.0) follows.

🤖 Generated with Claude Code

…rm_id — 0.8.0

Chair-approved 2026-08-24 (route "measure first"): the log had only
form_surface and a bare form_submitted, so per-stage latency was not
computable. This adds the lifecycle:

- FormSchema.form_id: explicit "form_id" definition key wins
  (validated token), else a deterministic content hash — render and
  collect re-parse the same dict, so both land on the same id with
  nothing threaded through the agent.
- form_build (source: dict|template:<name> — the V7 adoption signal),
  form_rendered (duration_ms, html_bytes), form_submitted(form_id),
  and form_id on form_surface records.
- stage_latency(): per-stage p50/p95 read-back (render cost +
  first-render→first-submission wait per form_id) with the same
  skip-don't-raise read contract as surface_mix.
- Shared _append write path; log_submission stays zero-arg-compatible
  for pre-0.8 callers (attune-ai <= 14.1.0).

Version 0.8.0 across pyproject + plugin + marketplace manifests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@silversurfer562
silversurfer562 merged commit 3f3f2bc into main Aug 24, 2026
7 checks passed
@silversurfer562
silversurfer562 deleted the feat/form-stage-telemetry branch August 24, 2026 19:46
silversurfer562 added a commit to Smart-AI-Memory/attune-ai that referenced this pull request Aug 24, 2026
…atency joins

Chair-approved 2026-08-24 (route "measure first"). attune-forms 0.8.0
(Smart-AI-Memory/attune-forms#59) adds per-stage form events joinable
on a deterministic FormSchema.form_id; this is the attune-ai half:

- _maybe_keyboard_hint takes the validated form and passes its
  form_id to log_submission, with a TypeError fallback so the handler
  keeps working on attune-forms 0.7.x (zero-arg signature, no form_id
  attribute) — no dependency floor bump needed.
- tests/unit/telemetry/test_form_events.py: stage-event tests through
  the attune.telemetry.form_events alias, skipif-guarded on the
  installed attune-forms capability (skip on 0.7.x, run on >= 0.8.0;
  verified green in BOTH modes locally).
- test_select_form_surface.py: the three routing-decision tests now
  filter form_surface events instead of counting raw lines — with
  0.8.0 the same log interleaves form_build/form_rendered stage
  events, and the raw count would break on the upgrade (the
  emptiness/count-assertion drift class from lessons).
- elicit skill Step 0: fix the stale template-store path
  (src/attune/elicitation/templates/ never existed here — templates
  live in the attune_forms package) and name the new adoption signal
  (template:<name> vs dict cast sources); mirrors + help reference
  re-projected.

Full suite: 25189 passed, 259 skipped, 6 xfailed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
silversurfer562 added a commit to Smart-AI-Memory/attune-ai that referenced this pull request Aug 24, 2026
…atency joins (#2278)

Chair-approved 2026-08-24 (route "measure first"). attune-forms 0.8.0
(Smart-AI-Memory/attune-forms#59) adds per-stage form events joinable
on a deterministic FormSchema.form_id; this is the attune-ai half:

- _maybe_keyboard_hint takes the validated form and passes its
  form_id to log_submission, with a TypeError fallback so the handler
  keeps working on attune-forms 0.7.x (zero-arg signature, no form_id
  attribute) — no dependency floor bump needed.
- tests/unit/telemetry/test_form_events.py: stage-event tests through
  the attune.telemetry.form_events alias, skipif-guarded on the
  installed attune-forms capability (skip on 0.7.x, run on >= 0.8.0;
  verified green in BOTH modes locally).
- test_select_form_surface.py: the three routing-decision tests now
  filter form_surface events instead of counting raw lines — with
  0.8.0 the same log interleaves form_build/form_rendered stage
  events, and the raw count would break on the upgrade (the
  emptiness/count-assertion drift class from lessons).
- elicit skill Step 0: fix the stale template-store path
  (src/attune/elicitation/templates/ never existed here — templates
  live in the attune_forms package) and name the new adoption signal
  (template:<name> vs dict cast sources); mirrors + help reference
  re-projected.

Full suite: 25189 passed, 259 skipped, 6 xfailed.

Co-authored-by: Claude Fable 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.

1 participant