feat(runtime): L1 resumable executor (execActions) + readable tail + fragment index - #36
Open
joelgwebber wants to merge 7 commits into
Open
feat(runtime): L1 resumable executor (execActions) + readable tail + fragment index#36joelgwebber wants to merge 7 commits into
joelgwebber wants to merge 7 commits into
Conversation
…fragment index
execActions(actions, args, options) runs an arbitrary Step[] with the same atomic step machinery as runTool, but swaps the outcome envelope: instead of throwing/hanging at the first action that doesn't cleanly resolve, it returns a structured ActionStatus (completedThrough, done, interrupt{at,action,reason,observed}, remaining). remaining is the untried tail beginning with the interrupted action -- a transparent continuation the caller resubmits to resume, blind or after editing a step. remainingView is a readable {op,target} projection of that tail (keeps predicate discriminators, not raw locator JSON).
fragments()/projectFragments(ir) expose the loaded IR's tool steps as a flat, pluckable index ({id, tool, index, op, label, uses}), so an agent composing an execActions list finds a step by the params it uses instead of scanning ir.tools[].steps.
Both are additive methods on the SightkickGlobal (window.__sightkick) host/console API -- NOT WebMCP tools (registration still exposes only ir.tools). This is the runtime primitive a 'fallback' exec tool would wrap later; nothing here registers or forecloses that. Validated end-to-end driving jetblue's checkout via browser eval; runtime suite green.
Signed-off-by: Joel Webber <joel@fullstory.com>
…it hook Add a self-installing pre-commit hook (.githooks/, wired through the package.json prepare script -> core.hooksPath) that rebuilds and re-embeds the runtime bundle whenever a commit stages packages/runtime/src/**, plus pnpm regen / regen:runtime / regen:skills / regen:inspector convenience scripts. This keeps generator/runtimebundle/sightkick-runtime.js from drifting, which CI's 'Embedded runtime bundle in sync' check otherwise catches only after the fact. Signed-off-by: Joel Webber <joel@fullstory.com>
…en-safe clicks) (#35) * fix(runtime): reach inner-child handlers via subtree descent (offscreen-safe clicks) clickElement routed its dispatch through document.elementFromPoint(centre) to land on the topmost node -- needed because a custom option often carries its handler on an inner child (jetblue: <jb-select-option> > div.body; a click on the outer node bubbles past the handler and no-ops). But elementFromPoint returns null for a point outside the viewport, so a far-scrolled/offscreen option fell back to the outer node and silently didn't commit. Replace it with deepestElementAt(root,x,y): descend the element's OWN subtree to the deepest node whose getBoundingClientRect contains the centre, then dispatch there so the event bubbles up to whichever inner node holds the handler. Own-rects are valid off-screen, so it reaches the inner child AND survives far-scroll -- no viewport dependency, no settle loop. The elementFromPoint variant is preserved as clickElementAtPoint (documented, unused) for the narrow hit-whatever-paints-on-top case. Validated live on jetblue's month/day/year/state/country selects (atomic, no scaffolding); 54 runtime tests green. Signed-off-by: Joel Webber <joel@fullstory.com> * chore(runtime): resync embedded runtime bundle The subtree-descent change to packages/runtime/src/dom.ts rebuilt the runtime bundle, but the committed copy embedded in the Go binary was not regenerated, so CI's 'Embedded runtime bundle in sync' check failed. Rebuild + re-embed via 'go generate ./runtimebundle/...'. Signed-off-by: Joel Webber <joel@fullstory.com> --------- Signed-off-by: Joel Webber <joel@fullstory.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
) * feat(generator): desugar signal completion predicates into IR waits Add a wait_for {signal: name} form and a step-level then: post-condition. Both reference a corpus signal (the SEP-0007 state-signal subset: a named boolean over a component's presence or a view's route) and desugar into an ordinary waitFor step -- a component ref becomes a present-wait on the component's selectors, a view ref a route-wait. Resolution runs against the whole corpus (Corpus.ResolveSignal), so a post-condition may name a subject in the destination view, outside the tool's ensure_view scope (the common click-continue -> wait-for-next-view case). then: expands to the action step followed by the signal wait, inheriting the step's when so an optional step and its post-condition skip together. A step then completes only once a named signal holds, not merely when the action dispatched -- the fix for a click that reports done while accomplishing nothing. Runtime is unchanged: the desugared steps are the query/route waits it already runs. Pins the sightmap library to the state-signals branch build for Corpus.Signals/ResolveSignal; bump to the released version once that lands. Signed-off-by: Joel Webber <joel@fullstory.com> * chore: add changeset for signal completion predicates Signed-off-by: Joel Webber <joel@fullstory.com> --------- Signed-off-by: Joel Webber <joel@fullstory.com>
PR #37 landed the signal-completion-predicates feature but kept generator/go.mod pinned to the state-signals branch build (v0.31.3-0.20260910214719-f6ac005ba83a). Now that sightmap v0.32.0 is released with Corpus.Signals / Corpus.ResolveSignal, replace the pseudo-version with the release tag. go build + go test ./... green. Signed-off-by: Joel Webber <joel@fullstory.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
joelgwebber
added this pull request to stack #42
September 11, 2026 23:35
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The runtime primitive we drove JetBlue's checkout through all along, graduated
from spike. Additive; touches only the
SightkickGlobalhost/console API.execActions(actions, args, options) -> ActionStatusRuns an arbitrary
Step[]with the same atomic step machinery asrunTool,but swaps the outcome envelope: instead of throwing / hanging at the first action
that doesn't cleanly resolve, it returns a structured status —
{ completedThrough, total, done, interrupt?{at, action, reason, observed}, remaining, remainingView }.remainingis the untried tail beginning with the interrupted action — atransparent continuation the caller resubmits to resume, either blind (opaque
continuation) or after editing a step (escape hatch).
remainingViewis a readable{op, target}projection of that tail — keeps thepredicate discriminators (
[label*="…"]) instead of dumping raw locator JSON.fragments()/projectFragments(ir)Projects the loaded IR's tool steps into a flat, pluckable index —
{ id, tool, index, op, label, uses }— so an agent composing anexecActionslist finds a step by the params it fills (
usesincludesfirstName) instead ofscanning
ir.tools[].stepsand string-matching interpolation values.Scope / non-scope
Both are additive methods on
window.__sightkick(the host/console API wedrive via
browser evaland thesightkick-debugflow) — not WebMCP tools:boot.tsstill registers onlyir.toolsondocument.modelContext. This is theprimitive a future "fallback" exec tool would wrap; nothing here registers or
forecloses that.
Validated end-to-end driving JetBlue cart → checkout → contact; runtime suite
green (execActions interrupt/resume, readable-projection, and fragment-index
tests).