Releases: EduDanielV/sett-framework
Release list
v0.14.0 - Durable evidence, deterministic authorization, and a separate execution boundary
Opt-in durable evidence and versioned state, pure recovery with explicit audit closure, copy-on-write migrations, deterministic authorization, and a separate execution boundary. SETT restores what durable evidence can support and never resumes interrupted work automatically.
✨ Added
sett.persistence:EvidenceStreamandStateRecordStorekeep append-only evidence separate from random-access state, bound byPersistenceBackend- Versioned binary formats for trace preimages, stream positions, stage-state envelopes, private-memory mutations, and migration manifests
- Durable trace evidence preserves the exact preimage used for each entry hash; recovery never reproduces a historical hash by reserialization
IntegrityPolicy,Sha256IntegrityPolicyandNoDigestPolicy; SHA-256 is documented as change detection, not authentication- In-memory reference implementations and a SQLite backend with transactional compare-and-append and idempotent state writes
- SQLite durability declarations come from effective pragma readback rather than requested settings
TraceRecorder.restore()for pure recovery andTraceRecorder.resume()for explicit continuationRecoveryReportseparates chain integrity, trace completeness, reconstructed outcome, unresolved boundaries, stage descriptors, and the last durable position- Durable stage-output persistence for
run_pipeline_controlled(), with materialization as a separate explicit operation - Opt-in
PrivateMemorypersistence through a stablememory_id; ordinary ephemeral memory is unchanged AuditClosureas an axis independent fromExecutionStatus, withAuditGapPolicyandSETTAuditClosureError- Append-only boundary dispositions with typed evidentiary bases
sett.authorization_ruler: closedGRANT/REQUIRE_APPROVAL/DENYvocabulary, detached requests with explicit field provenance, and store-backed receiptsReceiptUsedeclared per policy decision; replay requires unanimous policy consent plus a controlled request with an idempotency key- Versioned strict JSON authorization fingerprint with NFC text, signed-zero and integral-float normalization, and exact IEEE-754 hexadecimal for other floats
AuthorizationRequestResolverand optional paired executor configuration; once enabled, authorization is mandatory for every handlersett.execution_rulerowns the effect boundary that verifies authorization receiptsdocs/foreign_callers.md: the stable contract for governing an external tool loop with no dependency in either directionexamples/foreign_tool_loop.pyandexamples/governance_card.py, plus reusable adapter and phrasing-expert templates
🔄 Changed
SETTOrchestratoraccepts an optional backend and explicit persistence policy; durable execution is limited torun_pipeline_controlled()SETTAgentaccepts an optionalprivate_memory_id; omitting it preserves ephemeral behaviorExecutionResultcarriesaudit_closure, defaulting toNOT_REQUESTED- Trace event vocabulary and frame size are bounded before a lifecycle boundary can open, and only when persistence is enabled
- The documented concurrency roster now contains ten narrow guarantees
🐛 Fixed
- A durable terminal whose metadata is rejected records a framework-owned contingency terminal, so invalid terminal metadata cannot leave an already opened boundary unverifiable
- Distribution metadata now uses the PEP 639 SPDX form, declares
LICENSEthroughlicense-files, and no longer uses the deprecated license table or license classifier - The release builder now rejects unsafe destinations and option-like artifacts, handles command-line help safely, and fixes cross-platform ZIP entry metadata
- Corrected Convention #21 to record that v0.13.2 was subsequently published, without changing the rationale for its Pocket TTS exception
- Corrected stale Convention #9:
human_at_riskis an urgency and audit signal that can conservatively promoteALLOWtoWARN; it does not override the harm score - Completed the source-installation correction begun in v0.13.2 across adapter docs, runtime dependency errors, API examples, and test documentation
- Corrected
result_digest()documentation that described an unkeyed digest as unable to reveal its input - Corrected the public ethics description: numeric harm scoring comes from
ContextAnalyzer, not fromHarmCategoryweights or the rules list SQLitePersistenceBackend.open()now returns an object accepted directly bySETTOrchestratorverify()now documents that an interrupted run also returnsFalse, and points toRecoveryReportto distinguish interruption from corruption
🛡️ Audit remediation
- M-01: SQLite infrastructure errors are normalized without flattening the domain failures they must not hide
- M-02: world-readable SQLite files are documented rather than silently assumed safe
- M-03: an automated matrix now covers every declared Python version
- L-01:
SETTAdapterError.__str__()no longer carries provider-supplied text - L-02: template distribution corrected
🧹 Maintenance
CONTRIBUTING.mdfixes the lint gate to the Ruff version pinned inpyproject.toml- Convention #23 enumerates all eight structural pillars and records when the
Rulersuffix may name a class - Release archives use fixed cross-platform entry metadata and are byte-reproducible for identical source bytes under a matching Python/zlib toolchain
✅ Compatibility
- Persistence and authorization are opt-in and add no mandatory dependency; SQLite uses the standard library
- No v0.13.2 public symbol was removed or renamed
sett.SETTExecutorandsett.core_ruler.executorcontinue to resolve after the executor moved tosett.execution_ruler- Supported Python versions are 3.11, 3.12, 3.13 and 3.14;
requires-pythonis now>=3.11, correcting a v0.13.2 claim that never worked SETTAdapterError.__str__()drops provider text; structured attributes,safe_view(), reason codes and__cause__are unchanged. Code that asserted on provider wording inside a message must read__cause__- 1,255 tests pass, comprising the 1,038-test v0.13.2 baseline plus 217 new tests
- Automatic pipeline resumption, retention, compaction, cross-namespace migration, import, and production secret storage remain outside this release
⚠️ Architectural decision
Two structural pillars enter the framework. Authorization is promoted first and execution derives from it, so the dependency direction points away from the kernel. sett.core_ruler keeps its kernel contracts; its historical executor module is a compatibility reexport, and those kernel contracts have no runtime dependency on Authorization.
💖 Sponsors
Sponsors:
Eight tiers from a symbolic $1 up to logo placement on 4humanityAI.com
With explicit limits on what sponsorship does and does not buy.
See the complete itemized history in CHANGELOG.md.
v0.13.2 - Voice language consistency, audited boundaries, and optional Pocket TTS
Provider-neutral voice language consistency, audited error boundaries,
and optional Kyutai Pocket TTS support.
🐛 Fixed
LocalSTTAdapter.transcribe()now acceptslanguage_code, matching
GoogleSTTAdapterandAssemblyAISTTAdapter, and reduces a BCP-47 tag
to the bare language identifier faster-whisper expects (es-ARbecomes
es). The historicallanguagename remains a compatibility alias.
When both names are present, equivalent primary subtags are accepted
and a real conflict raises a structured configuration error instead of
silently allowing one spelling to overwrite the other.AzureTTSAdapterandAzureSTTAdapternow acceptlanguage_codeat
construction and per call. A call such astranscribe(..., language_code="es-AR")reaches Azure aslanguage=es-ARinstead of
being silently discarded in favor of the configured default.- The canonical spelling covers every official STT adapter that offers
language selection. Deepgram acceptslanguage_codeat construction
and per call; Gladia and hosted Whisper accept it per call. Whisper
reduces BCP-47 tags to the primary language identifier its provider
expects. - The historical
languagespelling remains a compatibility alias
where it already existed. Equivalent effective tags are accepted;
conflicts raise a structuredSETTServiceAdapterErrorwith
adapter.language_arguments_conflictbefore provider work. CartesiaTTSAdapterjoins Azure, Google, and LocalTTS in accepting
per-calllanguage_code, with the same compatibility and conflict
behavior.LocalTTSAdapternow normalizes failures raised while creating the
engine, reading voice metadata, or applying voice properties. These
paths no longer leak provider exceptions outside SETT's error
hierarchy.- pyttsx3 language matching now understands the control-byte prefix
emitted by older eSpeak metadata and underscore-separated locale tags.
Thelocal-ttsextra now requires pyttsx3 2.99 because pyttsx3 2.90
does not expose SAPI5 language metadata on Windows, making honest
language selection impossible there. - Local TTS and STT paths preserve cancellation and deadline exceptions
after provider work instead of translating them into service-adapter
failures. ContextAnalyzer.EMOTIONAL_RISK_MODIFIERSis now an immutable
mapping. One analyzer instance can no longer change the risk score
produced by every other instance through shared class state.
✨ Added
LocalTTSAdapter.synthesize()now accepts an optional
language_codekeyword argument, matchingGoogleTTSAdapter. Without
an explicitvoice_id, it looks for an installed host voice whose own
metadata names the requested language and leaves the current voice
untouched when none does. It deliberately does not guess from
free-form voice identifiers.PocketTTSAdapteradds optional Kyutai Pocket TTS 2.1 support
through the existingTTSBasecontract. It lazily loads a
caller-selected language and voice, accepts the conditioning forms
supported by Pocket TTS, and returns mono PCM16 WAV bytes. The adapter
declares six language families and voice cloning.- Pocket TTS generation is exposed honestly as non-streaming because
TTSBase.synthesize()returns one complete byte payload. The
underlying model's streaming API does not change SETT's current
contract. - One adapter instance serializes model loading, voice conditioning,
and generation because Pocket TTS documents its generation methods as
not thread-safe. The package and model remain optional; first use can
download model weights or catalog voices, while cached assets can
synthesize without a remote service.
🧹 Maintenance
- SETT now owns an explicit Ruff 0.16.0 policy in
pyproject.toml.
Repository validation no longer depends on whichever default rule set
an installed Ruff version happens to provide. The full tree passes
with zero findings. - Imports, annotations, unused test values, broad exception
assertions, intentional Unicode fixtures, and context-manager
structure were cleaned across the repository. Deliberate
audit-boundary catches remain in place with narrow inline
explanations. - Thirteen test modules now use stable, version-independent filenames.
Their names describe the contract under test, so future releases
update the same files instead of creating parallel version-labelled
suites. LocalSTTnow delegates language aliases, conflicts, primary-subtag
handling, and lowercase normalization to the shared_language.py
resolver instead of maintaining a second copy of the same rule.
📄 Documentation
README.mdanddocs/getting_started.mdnow document source
installation instead of presenting SETT as available from PyPI, where
it is not published.- Removed the unpublished draft Convention #24, which proposed a
repositorychecksums.txtpractice that was never present in the
released v0.13.1 archive. This entry records the governance edit
without presenting the draft as a released guarantee.
✅ Compatibility
- No public symbol was removed or renamed. Existing callers using
languagecontinue to work where that spelling already existed;
language_codeis the canonical spelling for provider-neutral call
sites. - The 1,003 tests of v0.13.1 pass unmodified.
- The complete v0.13.2 suite passes with 1,038 tests, 0 skipped.
- The private companion-assistant application's suite (1,162 tests)
passes against this source release with zero application code
changes. - SETT keeps zero mandatory dependencies.
pocket-ttsis available as
an opt-in extra, included only in theallextra.
⚠️ Versioning decision
PocketTTSAdapter is additive public API, which would ordinarily place
it in a minor release under this project's own versioning convention.
This is an explicit, one-time exception: Pocket TTS became known only
days before this release closed and addressed an immediate need for a
local CPU TTS option. Keeping the completed work in the same patch
avoided manufacturing two releases for one review cycle. This does not
redefine the stable API boundary and does not relax the default rule
for future additive public APIs.
💖 Sponsors
Sponsors:
eight tiers from a symbolic $1 up to logo placement on 4humanityAI.com,
with explicit limits on what sponsorship does and does not buy.
See the complete itemized history in
CHANGELOG.md.
v0.13.1 - Fail-closed routing preflight and benchmark-driven overhead fix
A frozen comparative benchmark exposed avoidable steady-state action
latency in SETT's governed execution path. Follow-up scenario-level
profiling and repeated ablation isolated two confirmed contributors:
synchronous logging.lastResort writes when the host application had
not configured logging, and governance work performed before handler
availability was known.
This patch fixes both causes while preserving fail-closed execution,
boundary integrity, sanitized trace completeness, and compatibility
with v0.13.0.
🔄 Changed
-
Importing
settnow installs a package-level
logging.NullHandlerwithout configuring the root logger.
Applications that never configured logging no longer fall through to
Python's synchronous stderrlastResorthandler. Handlers installed
by the application continue receiving propagated records normally. -
SETTExecutor.submit()resolves the exact handler before copying
payloads, reading environmental context, or invoking the
EthicalFilter. An unroutable action emitsaction.blockedwith
verdictblockand reasonhandler.not_registered, then raises a
structuredSETTConfigurationError. It does not manufacture an
ethical verdict or handler failure for something that never had a
route. -
SETTExecutor.submit_controlled()performs the same readiness and
route preflight before payload snapshots, fingerprints, idempotency
reservations, or handler-attempt events. An impossible action cannot
consume an idempotency key or fabricate an attempt that never reached
a handler.
🐛 Fixed
-
The concurrency reference now counts and names its five narrow
thread-safe exceptions consistently, includingUniversalMemoryin
the practical deployment guidance. -
CartesiaTTSAdapternow reports a blankvoice_idas a structured
SETTServiceAdapterErrorwith configuration metadata instead of
leaking a nativeValueError. -
The v0.13.0 changelog entry now includes release-audit changes that
were present in the published v0.13.0 source and release notes but
were mistakenly carried into the draft v0.13.1 entry. This corrects
the historical record and does not attribute those changes to this
patch. -
README.md's Install section documentedpip install sett-framework
as though the package were available on PyPI. It is not, and there is
no near-term plan to publish it. The section, and
docs/getting_started.md, now document installing from source.
Performance interpretation
Under the frozen SGBS-01 benchmark protocol, the repeated Stage 13
ablation measured, against the Stage 12 official run (three independent
repetitions each, run-to-run spread under 0.5%):
- Mean latency: 14.2% lower
- p95 latency: 23.8% lower
- p99 latency: 25.5% lower
- Throughput: 18.8% higher
These are observations under that protocol, not universal performance
guarantees.
The logging change affects emitted WARNING and ERROR records. The
routing change affects unroutable and unready actions. Neither removes
work from a registered ALLOW path.
The same ablation observed an approximately 7% improvement on registered
ALLOW-shaped paths. Those paths should not invoke either corrected
behavior, so that result remains unexplained and is excluded from the
patch's claimed effects pending isolated investigation.
The complete protocol, comparisons, and measurements will be published
separately as a citable benchmark report (SGBS-01).
✅ Compatibility
- Zero breaking changes. No public symbol was renamed, removed, or had
its contract narrowed. - All 995 tests inherited from v0.13.0 pass unmodified.
- The complete v0.13.1 suite passes with 1,003 tests.
- The private companion-assistant application's suite of 1,175 tests
passes with zero application code changes. - Zero mandatory dependencies were added.
💖 Sponsors
Sponsors:
eight tiers from a symbolic $1 up to logo placement on 4humanityAI.com,
with explicit limits on what sponsorship does and does not buy.
See the complete itemized history in
CHANGELOG.md.
v0.13.0 - Adapter capability contracts and opt-in resilience
Provider-neutral adapter contracts, honest capability selection, passive
health, structured failures, opt-in resilience, and an expanded voice
roster. Every adapter still ships present and importable, never
framework-selected: an application always names the one it wants.
✨ Added
- Immutable adapter contracts in
sett/core_ruler/adapter.py:
AdapterCapabilities,AdapterRequirements,AdapterHealth,
AdapterErrorView,AdapterHandle,AdapterSelection. Every
capability field is tri-state (yes / no / never declared), never a
plain boolean, and views are detached, JSON-safe copies. select_adapter(): pure filtering with a stable, explained rejection
reason per excluded candidate, passive health/circuit-state checks, and
caller-owned tie-breaking throughSelectionPolicy/
PrioritySelectionPolicy. SETT ships no provider default or
recommendation - selection policy belongs to the application.SETTAdapterErroras the structured common parent of the existing
SETTLLMAdapterErrorandSETTServiceAdapterError. Official adapters
now normalize authentication, quota, timeout, unavailable,
invalid-response, unsupported-capability and configuration failures,
always preserving the original provider exception as__cause__.CircuitBreaker,CircuitBreakerPolicy,CircuitStateand
execute_with_resilience()in the newsett.core_ruler.resilience.
Retry and circuit breaking are both off by default; retry additionally
refuses to run without an explicit idempotency statement.- Sanitized adapter trace events: call, health, retry, circuit and
fallback-selection. Prompts, audio, responses, credentials and raw
provider messages never appear in them. - Remote voice adapters: Deepgram STT, Azure Speech TTS/STT, AssemblyAI
STT, Gladia STT, OpenAI-hosted Whisper STT, Cartesia TTS. - Local voice adapters: pyttsx3 TTS, faster-whisper STT, Kokoro TTS,
Piper TTS. Model loading is deferred until first use where applicable,
so importing the module never pays a load cost the application doesn't
ask for. EdgeTTSAdapter, explicitly labeled community/unofficial in its own
docstring: it calls Microsoft Edge's reader-mode API rather than the
supported Azure Speech API, and callers should read that distinction
before using it commercially.sett.testing.adapter_contract: a dependency-free contract kit any
third-party adapter author can run without copying SETT's own test
suite, covering capability immutability, lifecycle honoring,
cancellation-before-contact, error normalization,__cause__
preservation, secret-free views, and honestUNKNOWNhealth.docs/adapters.mdandexamples/adapter_selection.py.
🐛 Fixed
- The internal execution-context conformance helper
_is_uuid()raised
NameErrorwhen called directly instead of importingUUIDfirst.
🔄 Changed
LLMBase,TTSBase,STTBaseandSentimentBasenow provide
concretecapabilities,healthand non-billablecheck_health()
members. Existing v0.12 third-party subclasses need no changes to gain
them.- All eight existing official adapters declare only the behavior their
current synchronous implementation actually has, and feed the same
passive health/tracing machinery as the new ones. - Retry moved from
sett.core_ruler.retrytosett.core_ruler.resilience,
alongside the new circuit breaker so both share one failure
classification. The old module path remains as a compatibility
re-export. CircuitBreakeris now covered by the documented concurrency
guarantees and an 8-thread, 2,000-failure stress test. A late failure
from a call already in flight no longer moves anOPENcircuit's
timestamp or postpones recovery; a failedHALF_OPENprobe still
starts a new recovery timeout.- The living adapter and execution-context design documents moved to
stable canonical paths (docs/adapter_contract.md,
docs/execution_context.md) instead of versioned filenames, so future
revisions update in place instead of creating parallel contracts. - Prose across the project now favors commas, semicolons, colons,
parentheses or a sentence break over a dash-shaped pause. Arithmetic
operators, list markers, changelog dates, ranges and tool directives
keep their functional symbols unchanged. - OpenAI, Anthropic and Gemini client construction now preserves
SETT-owned adapter, cancellation and timeout exceptions unchanged,
matching their real call paths, while genuine provider construction
failures still arrive normalized.
✅ Compatibility
- Zero breaking changes in this release.
- Every existing third-party adapter written against v0.12's
LLMBase/
TTSBase/STTBase/SentimentBasekeeps instantiating unmodified. - The 893 tests of v0.12.0 pass unmodified.
- Reference-consumer compatibility: the private companion-assistant
application's suite (1,175 tests) passes against this source release
with no application code changes beyond its own declaredsett-framework
version pin. The only local failures came from an audio-hardware gap in
the verification environment, unrelated to this release.
💖 Sponsors
- Sponsors: eight tiers from a symbolic $1 up to logo
placement on 4humanityAI.com, with an explicit note on what sponsorship
does and does not buy.
Known limitations
- No Capability Broker, credential/secret store, or billing/quota
handling ships in SETT. Provider selection by cost, plan or commercial
preference is deliberately left to the consuming application. - Health and circuit-breaker state live in process memory only; neither
persists across a restart. EdgeTTSAdapterdepends on an interface Microsoft documents for its
reader feature, not a supported API contract - stable in practice for
years, but outside the same guarantee the other adapters carry, and
flagged as such in its own docstring.- Declaring a capability as supported describes what an adapter's
current implementation does, not what a specific provider account,
plan or region will actually grant at call time. - The public namespace of the submodules (names without a leading
underscore that live outsidesett.__all__) still has no formal
policy; that decision remains deferred to the v1.0 freeze.
Status
- 995 tests passing (893 immediately before this release).
- Reference-consumer compatibility: the private companion-assistant
application's full suite (1,175 tests) passes against this source
release with zero application code changes beyond its own version pin. - Zero mandatory dependencies in the core framework. Every provider
integration, old and new (OpenAI, Anthropic, Gemini, Ollama, Google
Cloud, ElevenLabs, Deepgram, Azure Speech, AssemblyAI, Gladia, Cartesia,
pyttsx3, faster-whisper, Kokoro, Piper, edge-tts), is an optional extra.
See CHANGELOG.md for the complete, itemized history of this and every prior version.
v0.12.0 - Execution lifecycle, idempotency, and the first public release
Cooperative cancellation, deadlines, structured outcomes and idempotency
for executions already in flight, together with the hardening this
release's own auditing turned up along the way - several of those
fixes correct behavior that had been wrong since well before v0.12.0.
This is also the first public release of SETT: everything here was
already built and versioned internally (0.1.0 through 0.12.0), and this
is the first version anyone outside the project can install or link to.
✨ Added
- Immutable lifecycle primitives in
sett/core_ruler/lifecycle.py:
ExecutionControl,ExecutionControlRegistry,CancellationToken,
CancellationSource,CancellationSnapshot,Deadline. A control
carries its ownExecutionContext; subtree cancellation walks the
parent_idchain that context tree already maintains, so no second
hierarchy is introduced. - Cooperative cancellation with LIFO cleanup hooks, monotonic deadlines
a nested unit can shorten but never extend,lifecycle_scope()
propagation viacontextvars, andLifecyclePolicyfor per-level
timeout defaults - run, stage, agent, adapter, handler. ExecutionStatus,ExecutionState,ExecutionResult: six terminal
statuses that keep an ethical rejection, a cancellation, a deadline and
a technical failure apart.unwrap()re-raises the original exception
instance, preserving its concrete type.SETTOrchestrator.process_controlled()/run_pipeline_controlled()/
cancel(run_id), added alongside the existing entry points the same way
process_traced()was in v0.11.0.- Idempotency in
sett/core_ruler/idempotency.py:action_fingerprint(),
theIdempotencyStoreprotocol,InMemoryIdempotencyStore, and the
record/reservation/attempt types behind it. RetryPolicy,ErrorClass,classify_error(). Retries are opt-in
per error type; a set of framework errors is never retried regardless
of policy.SETTExecutor.submit_controlled(),register_controlled_handler(),
andHandlerContext, carrying the idempotency key and the run's real
remaining time into a handler.SETTCancelledError,SETTTimeoutError,SETTDependencyError,
SETTIdempotencyConflictError, all underSETTError.- Eleven new test modules.
🔒 Security
- Per-instance Google Cloud credentials: TTS, STT and sentiment adapters
no longer setGOOGLE_APPLICATION_CREDENTIALSprocess-wide, where two
differently configured instances used to interfere with each other and
with every other Google client in the process. - Sensitive metadata and trace keys were matched by plain substring, so
apiKey,x-api-key,api.keyandprivate/keyall passed. Keys are
now normalized to letters and digits before comparison. RiskProfilevalues could reachUniversalMemorythrough an
uncooperative agent despite the documented boundary. The check is now
structural, at the one place every publication passes through.
🐛 Fixed
- A non-finite
risk_scorefrom aContextAnalyzerreachedALLOW-
nancomparisons are alwaysFalsein Python, so a fail-open slipped
through the layer meant to fail closed. SETTExecutor.submit()andUniversalMemory.update()each read a
caller-held object twice; a concurrent mutation between reads could let
policy approve one payload while the handler performed another.PrivateMemory.get_history()returned live internal entries instead
of copies.ElevenLabsTTSAdapteraccepted a whitespace-only API key.- Provider SDK exceptions escaped adapter constructors untranslated
(OpenAI, Anthropic, Gemini, and Google client construction). Every
construction failure now leaves as a SETT error, with the original
preserved as__cause__. - Adapter timeouts skipped the
NaN/infinity validator this release
otherwise applies everywhere. - An invisible character (zero-width space, fullwidth spelling) was
enough to dodge aContextAnalyzerkeyword match; text is canonicalized
first now. OllamaAdapterlet a malformedbase_urlescape as a bare
ValueErrorinstead of aSETTLLMAdapterError.HandlerContext.attempt_numberreset to 1 on every resubmission of
the sameidempotency_keyinstead of climbing with it, the way
IdempotencyRecord.attempt_countalready did.
⚠️ Breaking changes
EnvironmentalContext.auto_notify_emergencyis now
should_notify_emergency(attribute andto_dict()key).register_expert()/register_handler()/
register_controlled_handler()/register_analyzer()now refuse a
duplicate instead of silently replacing it.register_agent()still
replaces - that is how aStubDomainAgentgives way to the real
implementation - but now warns when what it replaced was not a stub.
🔄 Changed
PrivateMemory.write()stores a deep copy;clear()now records an
audit entry too.- Timeouts and durations reject
NaNand infinity everywhere, through
onevalidate_duration_seconds(). - An
Actioncarrying anidempotency_keymust have a
JSON-serializable payload. docs/api_reference.mdnow covers every name insett.__all__, with
attribute tables for the four new exceptions; the concurrency section
namesExecutionControlRegistryandInMemoryIdempotencyStore. Every
public definition carries a docstring. Three new guard tests keep all of
this from drifting again.docs/SETT_Conventions_v2.mdis nowdocs/SETT_Conventions.md- no
version of SETT has been public before now, so no external reader ever
had a reason to link the old name.
🗑️ Removed
- The per-version
MIGRATION_v*.mdmechanism. No version has shipped
externally before now, so there is no adopter for a migration guide to
serve;CHANGELOG.mdis the record of what changed and why. - The per-release
AUDIT_vX.Y.Z.mdfile. OnlyAUDIT_v0.11.0.mdwas
ever produced under that name; no version before it had one, and this
release does not restart the pattern - a single instance was never a
convention to begin with.CHANGELOG.mdis the record of what was
verified for a given release and why.
✅ Compatibility
process(),run_pipeline()andsubmit()were deliberately not
rewired to their controlled counterparts in this release.- The 340 tests of v0.11.0 pass unmodified.
💖 Sponsors
- Sponsors: eight tiers from a symbolic $1 up to logo
placement on 4humanityAI.com, with an explicit note on what sponsorship
does and does not buy.
Known limitations
- SETT cannot cancel an arbitrary non-cooperative Python handler; three
levels of guarantee are documented (cooperative code, a provider given
the remaining time, untrusted code that belongs in an isolated process). - Exactly-once is not offered against an external system; an in-memory
idempotency store says nothing about anything before the current
process started. - Canonicalization does not defeat homoglyphs (Cyrillic
аvs Latin
a) - a hand-maintained confusables table would produce confidence
rather than safety. What guards a critical action isSETTExecutor
resolving handlers by exactaction_typeand failing closed, together
with a domain-specific analyzer. - The public namespace of the submodules (names without a leading
underscore that live outsidesett.__all__) has no formal policy yet;
that decision belongs to the v1.0 freeze. Full list inCHANGELOG.md.
Status
- 893 tests passing (828 immediately before this release's hardening
pass, 340 at v0.11.0). - Reference-consumer compatibility: the private companion-assistant
application's suite (1146 tests) passes against this source release
without any application code changes, with exactly one expected failure
(an intentional version-pin guard, unrelated to this release). - Zero mandatory dependencies in the core framework - every provider
integration (OpenAI, Anthropic, Gemini, Ollama, Google Cloud,
ElevenLabs) is an optional extra.
See CHANGELOG.md for the complete, itemized history of this and every prior internal version.
v0.11.0 - End-to-end execution traceability
End-to-end execution traceability: one trace_id now reconstructs
routing, broadcasts, agents, experts, native pipeline stages,
universal-memory publication, ethical decisions, action proposals,
handlers, results, rejections, and errors. An independent adversarial
review was run against the release candidate before publishing - every
finding reproduced against source and fixed (see AUDIT_v0.11.0.md).
✨ Added
- Immutable
ExecutionContext: generated or caller-supplied
trace_id/run_id, causalparent_id, UTC creation time, opaque
application/instance/subject/session/turn identifiers, recursively
frozen size-bounded metadata, andderive()for child operations. - Run-local propagation via
contextvars- bound only while a component
executes, always reset (including after rejection and exceptions). TraceEventand per-orchestratorTraceRecorder: thread-safe
structured events, monotonic sequence, SHA-256 hash chain, immediate
cause_idreferences, parent-run verification, sanitized export, and
exporter hooks.- End-to-end instrumentation across routing, broadcast, agents, experts,
pipeline stages, universal-memory publication, ethical decisions,
action proposals, handlers, results, rejections, and errors. SETTOrchestrator.process_traced()/TracedResult,get_trace(),
export_trace(),register_trace_exporter(),verify_traces(),
last_trace_id.- Stable generated
Action.action_idfor causal effect correlation. docs/execution_context_v0.11_design.mdandMIGRATION_v0.11.md.
🔒 Security
- Traces record operational metadata only - input/action payloads,
handler return values, exception messages/locals, biometric values,
risk profiles, prompts, model responses, and private-memory values are
excluded by default. - Metadata is bounded (32 top-level keys, depth 8, 16 KiB serialized) and
rejects sensitive key fragments and non-JSON objects. handler.authorizedis the committed pre-effect boundary: an exporter
failure there recordshandler.blocked, raises
SETTConfigurationError, and neitherhandler.startednor the real
handler ever runs.- Trace exports are defensive copies; hash and causal verification
detects mutation, removal, reordering, duplicate IDs, cross-trace/
forward causes, invalid parent runs, and incomplete instrumented
operations.
🐛 Fixed
tests/test_elevenlabs_adapter.pynow guards with
pytest.importorskip("requests")- already fixed as of v0.9.0 (see
that release), carried forward unchanged.
✅ Compatibility
SETTAgent.process(),SETTExpert.resolve(), executor handlers,
SETTOrchestrator.process(), broadcasts, and pipelines remain
source-compatible.execution_contextis additive and keyword-only.- The complete v0.10.1 suite passes unchanged.
- The private companion-assistant reference application's complete
baseline suite (842 tests) passes against this source release without
any application code changes.
Status
- 340 tests passing (290 before), 50 new (
tests/test_execution_context_v011.py). - Independent adversarial review: 8/8 findings reproduced and fixed - see
AUDIT_v0.11.0.md.
v0.10.1 - Documentation consistency and the Spanish-leak guard
Four documentation/consistency fixes, all found and fixed the same day,
squashed into one release since none had been published individually
(same reasoning as v0.7.0's own three-pieces-in-one-release precedent).
📝 Fixed
docs/security_model.mdclaimedPrivateMemory"intentionally retains
normal Python object identity" - true before v0.9.0, false since: that
release changedread()/get_all()to returndeepcopy()s (same
hardening already applied toUniversalMemoryin v0.8.0), but this
paragraph was never updated to match. Found by an independent
installation/upgrade validation exercise, cross-checking docs against
actual behavior rather than symbol inventory. Corrected, with the "why"
spelled out instead of just flipping the claim.docs/api_reference.md's
PrivateMemorymethod table now explicitly says "deep copy (since
v0.9.0)" for bothread()andget_all().sett/services_tts_stt/base.py's module docstring had a Spanish
paragraph that does not exist in the actual published v0.7.0 source - a
local-only artifact, never part of any released version. Removed, along
with five Spanish example strings elsewhere translated to English for
consistency (SETT is a general-purpose framework; its source should read
in English throughout).
✨ Added
docs/SETT_Conventions_v2.md: the framework's own conventions and
invariants document, published for the first time. Cited from source
since v0.7.0 ("Convención #N" /SETT_Convenciones_v2.md), but never
actually shipped - it only existed as a private working note used to
draft the project's arXiv paper. Translated in full; every citing site
acrossCHANGELOG.mdand three source files updated to the new name
and to English ("Convention #N").tests/test_no_spanish_in_public_tree.py: a new guard test, same spirit
and structure astest_no_internal_project_names.py. Scans the public
tree for text that looks like Spanish (accented vowels, n-with-tilde,
inverted question/exclamation marks) and fails if it finds any that
isn't on an explicit, documented allowlist (the framework author's real
name, the project's own "English, Español, 日本語" paper-language list,
a couple of necessary illustrative example words/names, and a couple of
historical CHANGELOG/README entries quoting already-fixed past mistakes
for the record). Deliberately not a grammar-aware classifier - manual
review before a release remains the backstop for the rare case of
Spanish written with zero accented characters - but this catches the
common case automatically going forward.
✅ Compatibility
Documentation and test-suite only. No code logic changed, no public API changed. 290 tests (up from 280 - 10 new, all in test_no_spanish_in_public_tree.py).
v0.10.0 - PhrasingExpert fact verification hook
✨ Added
-
PhrasingExpert.verify_facts(phrased, facts, context) -> str: an
optional fourth hook, called afterphrasedalready exists (from the
LLM if configured and successful, fromfallback_text()otherwise),
letting a subclass validate the ACTUAL text against facts already known
and swap it out if it contradicts them. Default implementation is a
pass-through (return phrased), so every existing subclass keeps
behaving exactly as before with zero changes required.resolve()now
calls it as part of its template:
determine_facts -> _phrase -> verify_facts.Motivated by a second-hand finding during an external audit: two
independent subclasses in a downstream project each needed this same
post-hoc check (a greeting that must never contradict the real time of
day; a reply that must never assert the wrong name for the user) and,
with no sanctioned hook for it, each had fully overriddenresolve()
just to insert one verification step - triggering the v0.9.0 override
warning in the process. Same origin story asPhrasingExpertitself
(see its class docstring): an unplanned repetition across independent
call sites is the signal that something belongs in the framework, not
copy-pasted per project. -
SETTOrchestrator.register_executor(self, executor: SETTExecutor):
added the missing type hint onexecutor(residual item from the
v0.8.0 audit, never part of the 8 accepted fixes at the time). Zero
behavior change.
✅ Compatibility
Fully backward compatible: verify_facts() is optional with a no-op
default, and does not change PhrasingExpert's existing abstract contract
(determine_facts/build_prompt/fallback_text are still the only
required overrides).
Status
- 280 tests passing (up from 275).
v0.9.0 - Public API audit and hardening
Eight findings from a full public-API audit of v0.8.0 - a symbol-by-symbol
inventory, then a phased pass over naming, signatures, exceptions,
mutability, subclassing contracts, documentation, concurrency posture, and
import surface. All eight accepted, none rejected. Same methodology as
always: nothing taken from a summary, every finding reproduced against the
actual source before deciding on a fix.
🔒 Added
SETTOrchestrator.verify_ethical_audit_log(): delegates to
EthicalFilter.verify_audit_log(), reachable from the orchestrator
itself instead of requiring access to the private_ethical_filter
attribute. Closes a real gap: v0.8.0's tamper-evidence guarantee was
invisible to anyone using only the documented entry point.SETTValidationError(SETTError, ValueError): deliberate multiple
inheritance, the same pattern the standard library's own
json.JSONDecodeErroruses.RiskProfile.__post_init__now raises this
instead of a plainValueError; bothexcept SETTErrorand
except ValueErrorstill catch it.- A non-blocking warning (logged, not raised) when a
PhrasingExpert
subclass overridesresolve()against its own documented "template
method, do not override" contract. Fires at instantiation, does not
prevent the override from working.
🐛 Fixed
PrivateMemory.read()andget_all()returned mutable references into
internal state: a caller mutating a nested value could corrupt stored
data without ever callingwrite(), with no trace inget_history().
Both now returndeepcopy()s, the same treatmentUniversalMemory
already received in v0.8.0.tests/test_elevenlabs_adapter.pynow guards with
pytest.importorskip("requests"). Previously, a bare install (pip install -e ., without the[elevenlabs]extra) made these 12 tests
FAIL instead of skip, contradicting the project's own documented
install instructions. Present unchanged since v0.8.0 as published.
🗑️ Removed
sett/services_gen_ai/: an empty scaffold module (a one-line docstring,
no classes, no functions, not referenced anywhere) since v0.1.0. Will be
recreated with real content if a concrete use case appears.
📝 Docs
api_reference.md: documentedSafetyAssessment,ContextAnalysis,
TTSBase,STTBase,SentimentBase,SentimentResult, and
SentenceSentiment- all public, exported, used in real tests,
previously undocumented. Added a field table forEthicalRule.
DocumentedEthicalFilter.verify_audit_log()/
SETTOrchestrator.verify_ethical_audit_log(), and addedsequence,
previous_hash, andentry_hashto the audit log field lists. Added an
explicit Concurrency section: no thread-safety guarantee for the
framework as a whole beyondUniversalMemory's internal lock.
✅ Compatibility
Low risk, but not zero: import sett.services_gen_ai now raises
ModuleNotFoundError instead of importing an empty module. RiskProfile
now raises SETTValidationError instead of a plain ValueError; existing
except ValueError handlers keep working unchanged, since
SETTValidationError is one. No other public signature changed.
Status
- 275 tests passing (264 before this round), 11 new.
- Full audit methodology and findings: see
CHANGELOG.md.
v0.8.0 - Fail-closed by default
🔒 Security and governance hardening
SETTExecutor.submit()now raisesSETTConfigurationErrorif the
Executor is not attached to aSETTOrchestrator, or if the attached
memory has noEthicalFilter. Previously an unattached Executor would
run the real handler with no governance at all.SETTAgent._publish_to_universal()andpropose_action()now raise
SETTConfigurationErrorinstead of silently returning when the agent
is not wired. A misconfigured agent no longer looks like it worked.UniversalMemory, the ethical audit log, the execution log, and
history now return defensive deep copies. External code can no longer
mutate internal state through a returned reference.- Memory history and both audit logs (ethical decisions and executed
actions) are now a sequenced SHA-256 hash chain, with averify_chain()
helper. Tamper-evident within the running process, not an external
signature.
🧠 Safety semantics
- Added
SafetyAssessment, separatingsituation_urgency,
action_harm_risk,omission_risk, andprotective_action. human_at_riskno longer inflates an action's harm score. The old
behavior pushed the score toreject_threshold - 0.01any time a human
was flagged at risk, which meant a genuinely protective action (like
calling for help) could get rejected precisely because the situation
was severe. Domain analyzers now decide harm; urgency stays a separate
signal.- New conservative fallback: if
human_at_riskis true, the action was
not classified as protective, and the base verdict isALLOW, the
filter promotes it toWARN. The score is untouched, protective actions
are never affected, and existingREJECT/WARNverdicts are never
downgraded or relabeled. The audit entry records
human_at_risk_without_protective_classificationunder
decision_reason_codes.
🔧 Fixed
examples/with_ethics.pyScenario 2 now actually producesWARN,
matching its own comment. It previously printed "expected: WARN" and
returnedALLOW.get_audit_log()/get_ethical_audit_log()no longer expose
internal dict references that could be mutated after the fact.
✅ Compatibility
- This release intentionally turns previously silent behavior into
explicit errors. If your code builds aSETTExecutororSETTAgent
outside a fully wiredSETTOrchestrator, wire it explicitly or expect
SETTConfigurationError. No other public signatures changed.
📝 Docs
MIGRATION_v0.8.mdwalks through every behavior change with
before/after examples.docs/security_model.mddocuments the hash chain, defensive copies,
and the exacthuman_at_riskpromotion rule.docs/api_reference.mdupdated for the new audit log fields
(situation_urgency,action_harm_risk,omission_risk,
protective_action,decision_reason_codes).
Status
- 264 tests passing (up from 244 in v0.7.0).
- Wheel built and installed in a clean environment; validated against a
private reference application (709/709) built on top of this release. - Python 3.13 declared supported after validation.