Skip to main content

kestrel-feature-talon

Portable Kestrel feature integration and runtime contracts for the external Talon coding-agent engine.

Package boundary

This distribution and the Talon engine have separate ownership:

Component Distribution / command Owns
Talon feature kestrel-feature-talon Kestrel SDK feature discovery, agent tools, permissions, Talon-specific completion/pipeline/fleet-coding sources, the talon:<job_id> wait provider, health checks, and setup integration
Workflow runtime kestrel-feature-workflows Public workflow models and execution contracts used by the fleet workflow registered and built by this feature
Talon engine kestrel-talon / kestrel-talon Issue processing, coding-agent execution, and its command-line runtime

Runtime health is exposed through the talon_health tool. The feature's synchronous health() method is a direct convenience probe; it is not a registered SDK health hook.

The 0.2 operator API supports launch, observation, pause, resume, and cancel. It deliberately does not support stage retry: Workflows 0.5 cannot pass fresh catalog/launch authority through its generic retry seam, so a generic retry of a failed Talon stage is terminalized without another engine dispatch. Launch a new governed run instead. Result fields for tests, review, demo, and Eye remain unknown/not_reported unless Talon supplies a bounded verified producer contract. Only Talon's bounded final claim-summary contract can populate PR identity today; arbitrary or partial log text is never promoted to evidence.

Installing this feature also installs its compatible workflow runtime dependency. It does not install or bundle the Talon engine. The host must install kestrel-talon separately and either put its executable on PATH or configure its absolute path as described below.

The compatibility ladder is intentional: Talon feature 0.2.0 is the migration bridge for Sovereign 0.52, where the bundled predecessor still exists. Talon feature 0.2.1 is the sole-owner release for Sovereign 0.53 and requires kestrel-sovereign>=0.53.0,<0.54.0; 0.53 supplies the public turn-bound session adapter needed to preserve durable completion wakes without reaching into core lifecycle internals.

Supported platforms: POSIX only

Linux and macOS, as pyproject.toml's classifiers say. This is a requirement of CLI dispatch rather than a preference: a dispatched job is launched as an sh wrapper script and identified for its whole lifetime by an inherited flock descriptor, and neither has a stock Windows form. Off POSIX no job can be dispatched, so no job exists to observe, pause, resume or cancel.

Nothing downstream of dispatch therefore carries a sys.platform branch. The cancel, pause/resume and process-teardown paths used to, and those branches were removed rather than brought into line: they could only ever have run against a job that could not have been launched, while reading — to the next person auditing the stop path — as a support claim this package does not make. Adding Windows support would start at dispatch (a wrapper that is not sh) and at identity (a portable lock in place of fcntl), not at termination.

Install and enable

Install the feature into the same Python environment as Kestrel Sovereign:

python -m pip install kestrel-feature-talon

Kestrel discovers TalonCoordinatorFeature from the standard Sovereign feature entry-point group. The wheel also publishes a pre-boot setup provider and the fleet_coding_pipeline workflow-to-feature ownership claim required by Sovereign 0.53. Capture the installed package in the host feature manifest so a later uv sync can be repaired, enable the feature if it was disabled, and restart the affected agent after enablement:

kestrel feature sync --capture
kestrel feature enable talon

On a host whose .kestrel-host-features.toml already declares the package, kestrel feature sync installs or restores it; --capture is only needed when first recording the currently installed extensions.

Run the optional Kestrel setup step to collect the engine's GitHub credentials:

kestrel setup talon

The setup step writes GITHUB_TOKEN and optional GITHUB_HUMAN_REVIEWER values to the host project's .env, preserving unrelated values and backing up an existing file before a change. It does not install the engine or choose runtime paths.

Runtime configuration

Paths are explicit and installation-independent. Configure them under [talon.runtime] in a host-selected TOML file, or provide the equivalent values through the host context:

[talon.runtime]
engine_executable = "/opt/kestrel/bin/kestrel-talon"
project_parent = "/srv/kestrel/projects"
running_agent_source_root = "/srv/kestrel/kestrel-sovereign"

The host supplies the TOML filename through the feature's config_path; the package does not select a global configuration file. A host may instead place the runtime mapping directly in the feature configuration or public talon_host_context.

Feature configuration applied through the SDK/HTTP configuration surface is stored atomically as talon_feature_config.toml with mode 0600 beside the stock agent's storage_path. On initialization, an explicit talon_config on the agent or its talon_host_context takes precedence; otherwise the feature loads that package-owned file. The file stores only the feature's config_path and direct runtime mapping—the host-selected TOML remains independently owned. A corrupt persisted file is reported as a configuration error and no runtime paths are inferred in its place.

Making fleet_coding_pipeline runnable: pipeline_mode

Contributing the pipeline is not enough to run it. workflow_run loads definitions from the agent's workflow store, and nothing consumes a contributed WorkflowRegistration into that store. An agent that dispatches the pipeline — Strategic Memory's signal_dispatch does, by default — opts in per agent:

# agent_data/<Agent>/kestrel.toml
[features.talon.config]
config_path = "/srv/kestrel/kestrel.toml"
pipeline_mode = "autonomous"   # or "consent"

At ready time the feature defines the chosen variant into that agent's own store through the governed workflow_define tool, signed with the agent's identity, and only if no live definition exists. consent keeps the approve_dispatch stage, so every run waits for a human in the Approvals tab before Talon writes code; autonomous omits it, and the safety moves downstream to the merge gate. With pipeline_mode absent nothing is defined — there is deliberately no default, because either default would be a signed write to every agent's store that never asked for one.

It runs off the boot path and calls as a feature lifecycle hook (session id feature-lifecycle). On an agent whose workflow tools require approval, a Sovereign that knows that id refuses the define at once rather than queueing an approval nobody is there to answer — logged at ERROR; grant the workflows tools ALLOW or define the pipeline once by hand. An older Sovereign queues the approval instead, which is answerable in the Approvals tab because boot has not waited on it.

It only ever adds a definition. To switch variant, revoke the live one (workflow_revoke_definition) and restart. A live definition of the other variant is reported by what it means: configured consent while the live pipeline is autonomous is an ERROR — runs are not waiting for anyone. A failed attempt is logged at ERROR naming the consequence, because the silent version of this failure left one agent's daily dispatch failing for 23 days (sovereign #3280).

A stored definition is signed and cannot change, so a release that changes the pipeline's spec ships it as a new version. "Present" means a live definition at that version or later. An older live one is superseded: the new version is defined beside it in the configured mode, and workflow_run starts the newest live version. The older row is left in place. Version 2 is the first such change. Version 1's talon_run stage fixed self_review: true, overriding the host preference on every run (#42), and recorded no job id (#43). If the new version cannot be defined, the ERROR names the older version runs keep starting, rather than claiming dispatch will fail.

The talon_run stage sets no run flag itself. self_review and skip_clarification come from [talon.preference] exactly as for talon_claim, unless the run's params state them. talon_claim, the pipeline and the operator API all resolve these values through one function, runtime.resolve_execution, so the same inputs launch the same argv on every path. skip_clarification stated on an iterate-mode run is refused, because kestrel-talon iterate has no clarification phase. The stage projects the dispatched job_id, log_path and wait_ref into the run params, so workflow_status and workflow_history name the job it started. This needs kestrel-feature-workflows>=0.7, the first version with stage output projection.

Version 3 (#46) holds no turn across the Talon run. Version 2's verify_ci waited on the job inside its own turn for at most 3600 s, so every run whose job took longer failed with job_still_running while the job went on to open its PR. Now talon_run dispatches and returns, and await_talon_job waits durably for a talon.job_settled event: an await_signal gate whose deadline is a Talon run's budget, 10 h (max_iterations × max_turns × 60 s at the preference defaults, four times over), not a held turn. The poll that sees the job go terminal publishes the event, addressed to the run, and the gate's predicate matches only the job_id that talon_run projected. So another job finishing never advances the run. verify_ci runs only for a settled job. A job that did not end complete with a completed disposition fails the run with that outcome as the reason (job_not_complete:blocked, plus the question). A completed job gets the existing CI probe against its PR head. If the deadline wins, talon_job_timeout fails the run with a talon_job_timeout reason that names the job and what it was doing.

The wait is a stage of its own, and read-only, because Workflows compensates a timed-out stage before taking its false branch. On the irreversible talon_run that compensation leaves residue, and the run would fail on a bare await_signal_timeout. A separate stage fixes its source boundary after talon_run returns, and the runner refuses any event committed before that boundary. So the stage's own effect arms the job first, and nothing is published for a job until it is armed.

Workflows keeps a run on the version it started on, so a v2 run in flight when v3 is deployed still goes from talon_run straight to verify_ci, and nothing armed its job. verify_ci no longer holds a wait for it. While that job is still running, the run fails with superseded_definition:v2 (job not terminal). The job carries on, and its talon.job_complete wake is delivered as usual. If the job has already finished, the v2 run's CI is verified as normal. The stored v1 and v2 definitions stay in place, and new runs start v3.

verify_ci judges CI on the run's own repository and the head of the PR its job opened. It looks for no check name of its own. With no branch protection to say otherwise, every check run and commit status at that head counts, so a repository with a single test check is judged on that one check. The run's reason says what kind of result it was (#51):

  • checks_failed: red, because a check concluded badly.
  • checks_timeout: checks were still running, or a required check never appeared, when the 30-minute CI window ran out.
  • checks_unavailable: GitHub returned no check run and no commit status for the head at all. A head with no checks is polled for the whole window, because checks register after the push, and this is the reason only if there are still none at the end.
  • checks_unreadable: no whole snapshot could be read. There was no token, GitHub refused or kept failing the request, or the answer could not be interpreted. This is final at once.

Each of these fails the run closed. A failed stage records only its error, so the error is where verify_ci writes what it judged: the repository, the PR head, each check with its conclusion, any required checks and, for checks_unreadable, the refusal, such as HTTP 403 from /repos/<owner>/<name>/commits/<sha>/check-runs.

GitHub serves a public repository's check runs to any token, but a private repository's only to a token allowed to read them. A fine-grained token needs Checks: read and Commit statuses: read on every repository the pipeline runs against. Without them, every private repository's runs fail as checks_unreadable while the public core repository's pass.

await_signal needs two host hooks that kestrel-sovereign 0.53.9 does not ship: workflow_await_signal_event_trust_verifier and workflow_await_signal_privacy_transition_lock (kestrel-sovereign#3484). On a host without them, Workflows refuses a v3 run at start, before Talon is dispatched. Deploy this release with a Sovereign that carries #3484.

Agents without a concrete string or pathlib.Path storage_path still accept configuration for the current process, but that configuration is deliberately ephemeral and will not survive restart. Generic os.PathLike objects and test doubles are not treated as state locations.

engine_executable takes precedence. When omitted, the feature performs only a normal PATH lookup for kestrel-talon; it never searches relative to its installed package or assumes sibling checkouts. project_parent and running_agent_source_root never have implicit filesystem defaults.

Talon workspace clones are kept under <project_parent>/.talon-workspaces/<owner>__<repo>. Every dispatch and verification operation rejects a workspace that contains, equals, or sits inside running_agent_source_root.

The package's TalonConfigAdapter reads and atomically updates the selected TOML file while retaining unrelated configuration values. Hosts may attach a talon_host_context mapping or object to the owning agent. In addition to the runtime paths above, the feature recognizes public context values for agent_name, did, dispatcher, storage_path, scheduler, observability_store, wait_registry, current_signal (or get_current_signal()), and origin_session_id (or get_origin_session_id()). This adapter keeps workflow/session correlation and durable job storage independent of private Sovereign agent fields. When that explicit context does not define an origin, Sovereign 0.53's public agent.get_turn_bound_session_id() adapter supplies the live turn's session; no private lifecycle compatibility alias is consulted. Likewise a context that does not define dispatcher or did leaves the agent's own public dispatcher and did in force, so a partial adapter cannot keep a job's talon.job_settled event from reaching the run waiting on it. A value the context does define, even None, overrides the agent's.

Tool and contribution contract

Version 0.2.1 preserves every tool of the public contract extracted from Kestrel Sovereign 0.52.0, and adds talon_cancel and talon_progress:

Tool Command prefix
scan_stale_work !talon scan-stale-work
talon_claim !talon claim
talon_file_and_claim !talon file-and-claim
talon_github_write !talon github-write
talon_get_config !talon config
talon_set_config !talon set-config
talon_verify !talon verify
talon_schedule_work_rescue !talon schedule-rescue
talon_workspace_status !talon workspace-status
talon_setup_workspace !talon setup-workspace
talon_batch !talon batch
talon_status !talon status
talon_job_log !talon job-log
talon_pause !talon pause
talon_resume !talon resume
talon_health !talon health
talon_cancel !talon cancel
talon_progress !talon progress

The 0.52.0 tool names, command prefixes, and parameter schemas remain compatible; the snapshot of that surface is a migration fidelity check, not a ceiling. talon_cancel stops one dispatched job's whole process group and records the outcome. Every talon_claim is dispatched as such a group: earlier releases preferred an A2A rail for an unattended claim with nothing customised, and a job dispatched there had no supported stop, because the A2A cancel endpoint marks the remote task canceled without reaching the process doing the work. That rail was removed rather than left half-cancellable; delegating a claim over A2A would return only together with a real stop contract. talon_cancel still refuses, fail-closed, any job that is not a local CLI process group — including a job talon_status listed from observability rather than from this coordinator's registry — and says so in its own error rather than reporting the job as unknown, because "no such job" reads as "already gone". When the group is provably stopped but the outcome could not be durably recorded, it reports cancel_unrecorded as a partial result instead of claiming the job was cancelled, and a retry re-attempts only the recording. Every signal it sends, escalation included, goes through the one function in the package able to signal a process group at all, which authorizes each signal against the job's group-owned identity re-read at that instant. So a group that exits during the SIGTERM grace period is never escalated onto through its reissued PGID, and a job dispatched without an identity is refused rather than signalled on the strength of a recyclable number. A job whose engine exited cleanly while something it started still holds the job's identity keeps reporting as running, from a restarted agent exactly as from the one that launched it, because a recorded exit describes the worker and not the job. That outcome is not discarded — it is applied once no holder of the identity is left. A job whose liveness cannot be established is reported as running with liveness "indeterminate" rather than as finished.

The bound on all of this is deliberate and worth knowing: liveness answers for the dispatch wrapper and the worker, which are what hold the job's identity. A descendant the engine starts with close_fds=True joins the process group without inheriting that identity, so once both holders have exited such a descendant is not observed — the job reports finished from the outcome the wrapper recorded while that descendant may still be running. Observing it would mean falling back on the bare, recyclable PGID, which is the thing the identity exists to replace; job_identity's module docstring records why the bound is accepted rather than widened. The talon_schedule_work_rescue description and behavior are an intentional Sovereign 0.53 disclosure correction: the command now refuses a schedule that cannot perform live Talon discovery instead of claiming a recurring rescue was installed. talon_claim gains two additive parameters, resume and resume_branch; every predecessor parameter is unchanged and both new ones are optional.

A finished job's talon.job_complete wake also carries its disposition — completed, clarifying, blocked, failed, or unknown — read from the processing summary Talon prints rather than from the exit code, because Talon exits 0 for a run that stopped to ask a question. A clarifying or blocked run is reported with that word and its question, not as completed, and the wake tells the orchestrator to answer on the issue, clear Talon's gate (agent-blocked, or 👍 / "ready" / agent-ready for a clarifying run), and re-dispatch from its own loop. A summary that cannot be read is unknown, never completed. A talon_pipeline_dispatch workflow stage that waits on the run applies the same rule: it reports state: "complete" (with its disposition) only for a completed run, and fails the stage closed — naming the disposition and the question — for any other.

Working or wedged: progress signals

Process liveness cannot tell a run that is editing files from a hung one, and Talon writes its job log only at iteration boundaries. So every running registry job in talon_status also carries three signals, read from what the run has produced:

  • last_activity_at: the newest mtime anywhere under the job's worktree, .git excluded, from one bounded lstat walk.
  • files_changed: the number of paths git diff <base_sha> reports, plus untracked files. base_sha is the commit the run started from, so the count is this run's own work and not drift against a moving main.
  • exit_file_present: whether the job's .exit sidecar exists.

talon_status also returns observed_at, the instant those timestamps are read against. talon_progress(job_id) is the detailed view and is kept off the common path. It adds the worktree's path, branch and base commit, a per-file diffstat, the untracked file list, one ps sample of the engine process (state, etime, CPU time and share, which separate waiting on the model from spinning), and when the log's last line was written, labelled as the least reliable signal. Its fields follow the epic's order: worktree, .exit sidecar, process, log.

The worktree is found through kestrel-talon's run locator (kestrel-talon#243). The first Run locator: <path> line of the run's own output names a run-locator.json recording the worktree, base commit, pid and process group. The coordinator never derives the engine's <repo>-issue-<n> layout. A locator is used only if its process group is the job's recorded pgid and it names the job's repository and issue (or pull request), because the file is rewritten by every run handed that worktree.

Everything the run can write is read as evidence and never obeyed. Git configuration can name programs that git runs while it only reads, such as core.fsmonitor, a clean filter, an external diff or textconv. The run's repository, worktree and user configuration are all writable by the coding agent. So the diff and the untracked list are read through a private git directory that the coordinator writes for each observation. It holds a copy of the run's index (with the shared index a core.splitIndex index names) and exclude patterns, a configuration naming only the object format, and read-only access to the run's objects. Nothing reads the run's configuration there, apart from a few settings that change what git reports and name no program: ignore rules, case, file modes and line endings. Submodules are compared by their recorded commit. Because the index is a copy, polling a live run never takes the index.lock that the agent's commits need. Every string either tool returns, including the worktree path, branch, file names and log line read from those files, passes through one redaction step before it reaches tool output.

Absence is not zero. Some signals cannot be observed. Examples are a batch job (no single worktree), a run dispatched without --worktree, a run that has not printed its locator yet or reported it could not write one, a locator written by another run, a worktree that is gone, a walk that exceeds its bound, and a git command that fails. Each such field reads "unknown", and progress_unknown maps the field to the reason. It is never 0, [] or null, so a quiet run and an unobservable run never read the same.

The same dispositions are what kestrel-sovereign's signal_dispatch reads, through the wait provider's read-only finished_runs(), to avoid re-dispatching an issue whose last run asked a question nobody has answered. That read reports whether it covered every job in the registry. A registry that exists but cannot be read whole — corrupt or oversized jobs.json, a record it cannot interpret, or a finished job whose log is gone — is reported incomplete with the reason, and dispatch stops with RUN_HISTORY_UNCONFIRMED rather than treating it as no history. An agent that has never dispatched a Talon job has no registry yet, and that is an empty history.

signal_dispatch picks across every repository in scan_repos. A fleet_coding_pipeline run for a repository nobody has provisioned fails at talon_run within milliseconds, unattended (#50). The ruling on #50 is that the selector skips such a candidate with the typed reason no_talon_workspace and names it in its output, so the run is never started. The skip belongs to kestrel-sovereign's selector (kestrel-sovereign#3548). What it reads comes from this package, from the same wait provider: workspace_readiness(repo). The answer is {"repo", "provisioned": true, "workspace"} when the claim would run. Otherwise provisioned is false and reason says why. It is either no_talon_workspace, which also gives the workspace path and the next_step (talon_setup_workspace(repo='<owner>/<name>')) that provisions it, or talon_workspace_unusable, when provisioning would not help: Talon's runtime paths or policy are unconfigured or unreadable, or the path overlaps the running agent's own source tree. detail is the refusal the dispatch itself would give. The read provisions nothing. talon_setup_workspace stays approval-gated, and a repository becomes dispatchable only when an operator runs it. The answer comes from the same rule that talon_claim, the pipeline's iterate branch and talon_batch apply before they launch, so the read and the dispatch cannot disagree.

This package supplies only that read. Until a kestrel-sovereign that carries #3548 is deployed, signal_dispatch does not ask. A run for an unprovisioned repository is still started and then fails at talon_run, as before.

The feature also contributes the agent-scoped talon.coordinator service, the talon:<job_id> wait provider, Talon completion/pipeline/fleet-coding workflow sources, conservative permission defaults, and the optional setup step. Generic stalled_work_rescue sources remain host infrastructure; Talon does not register or override them. Sovereign 0.53's generic sweep is echo-only, so talon_schedule_work_rescue refuses to create a recurring no-op and points operators to scan_stale_work for live Talon findings. scan_stale_work is allowed for unattended discovery; every other Talon tool defaults to operator approval.

talon_pause writes a private durable dispatch marker and CLI dispatch checks it before any external effect. The marker survives agent restarts; talon_resume clears it explicitly. These tools do not depend on a retired core scheduler task. talon_file_and_claim treats its audited GitHub issue creation and Talon launch as two explicit boundaries: a pre-existing pause prevents the GitHub write, while a pause requested during approval or issue creation takes effect immediately and blocks the later dispatch. In that race, the tool reports the already-filed issue as a partial outcome for manual review.

Preserved work from a failed run

When a run fails, kestrel-talon commits what the agent produced and keeps the checkout. talon_claim(resume=True, resume_branch=...) continues that checkout rather than preserving it aside and branching fresh — the two coordinates of the recovery command a failed run prints. They arrive together on purpose: resume without a branch continues whichever issue-<n>-* branch the checkout happens to be on, which is the hole resume_branch closes. The tool carries the engine's own refusals instead of relying on a background subprocess exiting 2 where nobody reads it, so resume without a worktree, resume without a concrete issue, and resume_branch without resume (including an empty one) are refused with nothing dispatched. This is unrelated to talon_resume, which un-pauses dispatch.

Two behaviors around that checkout are the feature's own:

  • A fresh claim is refused when a previous attempt at the same issue holds work that exists nowhere else — unpushed commits, or an uncommitted tree. Talon preserves such a checkout aside rather than deleting it, so nothing is destroyed either way; what the refusal prevents is the work moving one talon-preserved-* directory further from anyone looking for it with no trace of that in the dispatch result. The refusal names the checkout, its branch, and the exact resume call that continues it. Work that is already pushed never blocks a claim.
  • When a job ends without succeeding, its preserved branch is pushed, so the commits stop being the only copy. Never forced, never committed on the run's behalf, and never against a branch that does not belong to the job's issue; a job still holding its group-owned identity is left alone until it is really over. The outcome — including a rejected push — is recorded on the job record rather than left to be inferred.

Both act on the branch the checkout is actually on, re-read from git, never on the directory name that suggested looking there.

The host-scoped TalonHostFeature owns /api/talon, a capability-gated Talon panel, lifecycle workers, and the talon.operator service. Manual claim and approved-batch launches accept only opaque values resolved through claws.catalog>=1.1.0, while durable run state and artifacts are projected through workflows.runs>=1.0.0. Configure the same runtime paths under [talon.runtime]; operator_state_path may additionally select the private checksum-bound intent/evidence root. If omitted, it is placed beneath the explicit project_parent.

Hosts may inject a Castle or Workflows operator_context_resolver; that resolver always takes precedence. Without one, the operator API resolves the authenticated single-tenant policy through claws.catalog>=1.3.0. Missing or incompatible policy services fail closed.

Referenced operator evidence is never evicted behind an active or completed run API. The private store instead enforces a fail-closed retention ceiling of 10,000 run directories and 128 MiB of evidence; once either bound is reached, new artifact finalization is refused until an operator archives the state root or provisions a larger policy in a future release. Expired pre-dispatch intents are pruned off the event loop, while dispatched and linked intents remain recoverable until their external job is finalized.

Development

uv lock --check
uv run --extra test pytest -q
uv build
git diff --check

The wheel and source distribution are built from this repository alone. No sibling checkout or editable/path dependency is part of the package metadata.

Metadata

Release files for kestrel-feature-talon 0.2.13

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kestrel-feature-talon 0.2.13
File Size Uploaded
kestrel_feature_talon-0.2.13.tar.gz 600.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for kestrel-feature-talon 0.2.13
File Interpreter ABI Platform
kestrel_feature_talon-0.2.13-py3-none-any.whl Python 3 none any Details

Total release size: 853.7 kB

Release files / kestrel_feature_talon-0.2.13.tar.gz

Download URL kestrel_feature_talon-0.2.13.tar.gz
Size 600.5 kB
Tags Source
SHA-256 checksum
How to use checksums
c8ce81b82364e7a3837e053575c9ba4a07fd2c95f7c34c897b804db944ca74f9
BLAKE2b-256 checksum
How to use checksums
30ecd082d624f6a833b8366c231ef09b760c33b2d7acfc35e65429ca1b05ba12
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Release files / kestrel_feature_talon-0.2.13-py3-none-any.whl

Download URL kestrel_feature_talon-0.2.13-py3-none-any.whl
Size 253.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8e21f35896f3e40e96adb4f03b7913f9318bd7bf7f579831ed79619bcde3f159
BLAKE2b-256 checksum
How to use checksums
898960286fb2be38cc93a74838d5e0d9437e3b35ece6f4ea16351d5ffa237351
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.13 This release

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page