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:
| Field | Value |
|---|---|
index1 | package_invoke_specifier_form_migration |
blob1 | same form value |
blob2 | execute, package, job, or app |
double1 | 1 |
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:
- Inspect every returned row, including sampled rows. Any observed
prefixlessrow withretained_calls > 0fails and restarts the entire telemetry gate. Reset every surface's confidence accumulator and resume with the next fixed window. - For each surface, take the maximum
max_sample_intervalacross its form rows. A window with at least one row and a maximum of1may contribute retainedkody_prefixedliveness counts for that surface. This selection depends only on sampling, never on form outcome. - Do not infer zero from a missing
prefixlessrow. Form is stored in non-indexedblob1; 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. - 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.
- Sampled or missing surface-windows add no confidence counts, but remain in
the ordered evidence ledger. Sum
weighted_callsby 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:
- Executable source: fleet scan
803e3045reports 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. - Telemetry: an absence-capable proof source exists for every runtime
surface. Since the most recent prefixless observation (or from window
0when none has occurred), predeclared disjoint windows with that proof accumulate, independently forexecute,package, andjob, at least 300 retained calls total, at least 30 retainedkody_prefixedcalls, and zero retainedprefixlesscalls. Ifappis 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):
| Surface | Retained prefixed | Weighted prefixed | Maximum sample interval |
|---|---|---|---|
execute | 63 | 76 | 2 |
job | 86 | 86 | 1 |
package | 71 | 71 | 1 |
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:
- Every closed fixed window number and exact UTC bounds, in order, including sampled and empty surface-windows.
- The exact supported query and every grouped result row.
- Prefixless reset points, per-surface liveness accumulators, and the independent form-aligned unsampled proof used to establish zero.
- Dataset name, index values, telemetry deploy link, and deployed commit.
- Fleet scan
803e3045totals 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.