packages.invoke prefix migration

August 25, 2026 ยท View on GitHub

Soak telemetry and codemod notes for the quarantined kody:runtime packages.invoke helper (0037, #1750). Authors and agents do not get that helper; this page is for operators migrating leftover published calls.

The string-first helper accepts both kody:@owner/package[/export] and the deprecated prefixless @owner/package[/export] form. The parser canonicalizes the latter to kody:. Object-only invocation is rejected, and publishing does not reject prefixless string-first calls.

Use permanent codemod 0007-prefix-packages-invoke-specifiers to migrate literal calls and parseable dynamic first arguments. Dynamic calls receive an inline once-only normalizer that prefixes trimmed @... values and passes other values to the existing runtime parser unchanged. Unparseable and binding-ambiguous calls remain manual; there is no binding-blind textual fallback. 0007 is intentionally separate from 0006-invoke-object-to-specifier, which retains responsibility for the removed object-only API.

Privacy-safe telemetry

Every string-first call is classified before parser canonicalization and written to the dedicated production Analytics Engine dataset kody_package_invoke_specifier_events (preview uses kody_package_invoke_specifier_events_preview).

The schema is deliberately coarse:

FieldValue
index1package_invoke_specifier_form_migration
blob1same form value
blob2execute, package, job, or app
double11

No user, package, specifier, export, params, source, run, request, or conversation identity is recorded. Recording is nonthrowing and a no-op where the binding is absent. Both forms use the same constant index1, so they share one Analytics Engine sampling population; form remains only in blob1.

Attribution is deterministic: a parent job run selects job; otherwise an app runtime marker selects app; otherwise an execute caller selects execute; all remaining calls select package.

Fixed-window query procedure

The evidence schedule is fixed before reading form outcomes. Window n is the one-hour interval [2026-08-23T21:22:35Z + n hours, 2026-08-23T21:22:35Z + (n + 1) hours), for integer n >= 0. Query every closed window in order. Never skip, reorder, overlap, resize, or combine windows in response to their form results.

Run this query separately for each window against kody_package_invoke_specifier_events. Replace only the two UTC timestamp literals with that window's exact bounds, using Analytics Engine's accepted YYYY-MM-DD HH:MM:SS format. This example is window 0.

SELECT
  blob2 AS surface,
  blob1 AS form,
  COUNT() AS retained_calls,
  MAX(_sample_interval) AS max_sample_interval,
  SUM(_sample_interval) AS weighted_calls
FROM kody_package_invoke_specifier_events
WHERE timestamp >= toDateTime('2026-08-23 21:22:35')
  AND timestamp < toDateTime('2026-08-23 22:22:35')
  AND blob1 IN ('prefixless', 'kody_prefixed')
  AND blob2 IN ('execute', 'package', 'job', 'app')
GROUP BY surface, form
ORDER BY surface, form

The query returns one row per surface and form. Process each closed window before moving to the next:

  1. Inspect every returned row, including sampled rows. Any observed prefixless row with retained_calls > 0 fails and restarts the entire telemetry gate. Reset every surface's confidence accumulator and resume with the next fixed window.
  2. For each surface, take the maximum max_sample_interval across its form rows. A window with at least one row and a maximum of 1 may contribute retained kody_prefixed liveness counts for that surface. This selection depends only on sampling, never on form outcome.
  3. Do not infer zero from a missing prefixless row. Form is stored in non-indexed blob1; Analytics Engine may omit a rare blob subgroup even when returned rows have _sample_interval = 1. The shared constant index does not make this grouped query absence-capable.
  4. Zero-prefixless confidence requires an independent proof covering the exact surface-window: either a form-aligned query/source with a documented unsampled absence guarantee, or another durable unsampled event source. The current dataset/query does not provide that proof, so the removal gate cannot yet complete.
  5. Sampled or missing surface-windows add no confidence counts, but remain in the ordered evidence ledger. Sum weighted_calls by surface/form for reporting only; weighted values never enter the confidence gate.

Cleanup gate

Remove prefixless runtime and type support only when both safety gates pass:

  1. Executable source: fleet scan 803e3045 reports 307 clean packages, zero executable-source findings, zero drift, and zero errors. Its three remaining findings are private README-only documentation and cannot execute. They do not block runtime/type removal once telemetry passes.
  2. Telemetry: an absence-capable proof source exists for every runtime surface. Since the most recent prefixless observation (or from window 0 when none has occurred), predeclared disjoint windows with that proof accumulate, independently for execute, package, and job, at least 300 retained calls total, at least 30 retained kody_prefixed calls, and zero retained prefixless calls. If app is active, it must independently meet the same thresholds.

The fixed windows are disjoint, so calls included for one surface are never double-counted. Predeclaring every window and selecting solely on sampling and the independently documented proof source prevents cherry-picking based on the desired zero outcome. Once absence-capable windows accumulate 300 unsampled calls, they support the rule-of-three target (an approximate one-sided 95% upper bound near 1% under independent calls). Thirty observed kody_prefixed calls separately prove that each surface is live. Every Analytics Engine window must still be queried: an observed prefixless row in a sampled or unsampled window restarts the gate.

The three README-only findings remain aggregate owner-action documentation debt. Track their count without publishing private package ids or owners. Keep codemod 0007 and the local prefixless teaching error available to repair those docs; do not treat documentation debt as executable compatibility risk.

Current evidence

The cumulative check recorded in issue #1702 covered [2026-08-23T21:22:35Z, 2026-08-24T19:30:00Z):

SurfaceRetained prefixedWeighted prefixedMaximum sample interval
execute63762
job86861
package71711

No prefixless or app rows were returned. This is non-qualifying historical evidence: execute was sampled, and absence of a non-indexed form cannot be inferred from the returned rows. Analytics Engine may choose a different read resolution for shorter time ranges, so this result does not establish the capacity of any fixed one-hour window. The operator must replay fixed one-hour windows from window 0 in order, but those queries cannot complete the zero-prefixless gate until an independent absence-capable proof source exists.

Attach the following evidence to the final cutover:

  1. Every closed fixed window number and exact UTC bounds, in order, including sampled and empty surface-windows.
  2. The exact supported query and every grouped result row.
  3. Prefixless reset points, per-surface liveness accumulators, and the independent form-aligned unsampled proof used to establish zero.
  4. Dataset name, index values, telemetry deploy link, and deployed commit.
  5. Fleet scan 803e3045 totals plus the aggregate count of README-only debt; never publish private package ids or owners.

Keep this telemetry and its bindings through the final prefixless cutover. Remove it only after the cutover is deployed and verified; the cleanup issue for that later work is owned by the parent migration track.