Changelog
All user-visible Oko changes are recorded here, newest release first. Oko is a macOS desktop application; every published release ships a signed application archive plus a Sparkle appcast.xml, and installed copies update through that feed.
Releases up to and including v0.2.11 were published from .github/workflows/release.yml with the body text Automated release <version> and carried no release notes. Every section below was therefore reconstructed after the fact from the Git diff between consecutive published tags; each section says so explicitly. Work merged after v0.2.11 has not been released and is not described here.
v0.1.0 is a GitHub draft release and never became a published artifact, so it has no section. v0.2.5 was never tagged or published; the jump from v0.2.4 to v0.2.6 is expected.
Unreleased
Added
oko-cli autonomypersists experimental or full delegated authority, selects eligible active goals, executes them through Jeden Pursuit, and closes a goal only after a successful receipt and independent acceptance verdict.- The installed
run-autonomy-servicelauncher keeps scheduler ticks alive as a Stado-managed service instead of depending on the desktop app.
Safety
- Experimental mode is limited to the signed-in local user, one accepted goal per day, repository work under the Wisent workspace, and no purchases, irreversible external actions, release publication, or service mutation.
- Failed attempts are retained and retry after a 15-minute backoff; they do not consume the successful-outcome daily limit.
Minimum supported system is macOS 14.0 (LSMinimumSystemVersion). The goals, daily/period digest and telemetry-writing features depend on Apple Foundation Models and are compiled behind #available(macOS 26.0, *): on macOS 14 and 15 they are inert, not degraded.
0.2.11 - 2026-06-25
Reconstructed from git diff v0.2.10 v0.2.11 (392 files) because the release was published without notes.
Removed and renamed — product identity
- The product is now Oko. The previous name Swiatowid is gone from the shipped surface: application bundle
Swiatowid.app→Oko.app, bundle identifierai.wisent.swiatowid→ai.wisent.oko, SwiftPM productsSwiatowid/SwiatowidKit/swt-cli→Oko/OkoKit/oko-cli, and the release archiveSwiatowid-<version>.zip→Oko-<version>.zip. - The OAuth callback URL scheme changed from
swiatowid://tooko://(CFBundleURLNameai.wisent.oko.oauth). The old scheme is no longer registered. - The user configuration directory moved from
~/.swiatowidto~/.oko. - The rebuild/relaunch skill was renamed
swiatowid-rebuild-relaunch→oko-rebuild-relaunch. - Release signing environment variables were renamed
SWIATOWID_SIGN_IDENTITY→OKO_SIGN_IDENTITYandSWIATOWID_ALLOW_ADHOC_SIGNING→OKO_ALLOW_ADHOC_SIGNING.
Added — organization membership
- Added organization management: invite by email with a role, cancel an invite, accept an invite, list members and invites, remove a member, and change a member's role. Surfaced by
OrganizationSettingsView,InviteAcceptanceViewandOrganizationStore. - Added first-sign-in bootstrapping, so a new account provisions its own organization membership instead of requiring a manual backend row.
Added — company context and advisor
- Added an on-device company-context extractor and a company advisor pane that reads execution signals from GitHub (
CompanyAdvisor,CompanyContextExtractor,GitHubExecutionSource), plusoko-cli adviseandoko-cli snapshot-contextheadless equivalents. - Added an orchestrator planner, an advisor path and correction write-back, so a human correction feeds back into later suggestions.
- Added team-wide goals views (
TeamGoalsAllDaysSection,GoalsWorkTodaySection) and org-level goal materialization.
Added — terminal and suggestions daemon
- Added a supervised PTY broker and an explicit PTY permission sandbox (
PTYBrokerSupervisor,PTYPermissionSandbox), and a terminal agent provider selected by a stable provider id. - Added a headless suggestions tick (
oko-cli suggestions tick) with strategy, team, velocity, assignment, Slack and model-fallback stages, plus the launch agentdeploy/ai.wisent.oko.suggestions.plistso suggestions can run without the app in the foreground.
Added — subscription cost accounting
- Added a provider-subscription catalog and router. Token telemetry can now be attributed to a fixed subscription charge instead of metered list price:
Resources/subscriptions.example.jsondeclares per-subscriptionperiodCostUSD,coveredModelPatternsand optionalowners, andResources/subscription-router.example.jsonpoints at the central model-router endpoint. - Model list prices moved out of Swift source into the bundled resource
Sources/OkoKit/Resources/token-pricing.json.
Configuration changes
- Optional new files, both read from
~/.oko/:subscriptions.jsonandsubscription-router.json. Both are compatibility fallbacks only — the source of truth isGET /v1/subscription-router/{agentId}on the model-router service. - Optional new environment variables for the router secret:
OKO_ROUTER_AUTH_SECRETorMODEL_ROUTER_AGENT_SECRET. Placing the secret in the JSON file is supported but not preferred.
Data and state migrations
- New Supabase migrations, applied to the backend project rather than to device-local state:
20260618190707_bootstrap_user,20260618191708_org_invites(addspublic.organization_invitesplus the invite/member RPCs and theirauthenticatedgrants),20260620190000_prefer_team_org_membership(a signed-in user resolves to their team organization rather than a personal one) and20260620203000_org_member_auto_goals_upsert. Several follow-up migrations correct return types, ambiguous identifiers and role casts in the same RPCs. - The transcript-object SQL definition was renamed
swiatowid_transcript_objects.sql→oko_transcript_objects.sql.
Compatibility requirements
- The renamed bundle identifier and the new update feed mean this release is not an in-place upgrade of an installed Swiatowid build. The old and new applications are distinct to macOS, to Sparkle, and to every macOS permission grant.
- The Sparkle feed moved from
https://storage.googleapis.com/wisent-swiatowid-updates/appcast.xmltohttps://storage.googleapis.com/wisent-oko-updates/appcast.xml. A copy still pointed at the old feed will not discover this or any later release.
Operator actions required
- Install
Oko.appexplicitly; do not expect the Swiatowid feed to deliver it. - Copy any local state from
~/.swiatowidto~/.okobefore first launch. - Re-grant the macOS permissions the app asks for (Automation/Apple Events and the Messages database read used by Ultrareach); grants are keyed to the old bundle identifier and do not carry over.
- Apply the new Supabase migrations before signing in, otherwise organization bootstrap and invite handling will fail.
- Remove the old Swiatowid application and its login items once Oko is verified.
Known limitations
- Company-advisor GitHub signals require a reachable GitHub token; the pane has no offline mode.
- Subscription cost attribution is only as good as the manually entered
periodCostUSD; the example file ships the literal placeholderREPLACE_WITH_REAL_BILLED_AMOUNT.
0.2.10 - 2026-06-17
Reconstructed from git diff v0.2.9 v0.2.10 because the release was published without notes.
Added
- Added Google as a second sign-in provider. The GitHub-specific PKCE flow was generalized into one provider flow (
signInWithOAuth(provider:label:),oauthAuthorizeURL(provider:…)), and the sign-in screen now offers "Continue with GitHub" and "Continue with Google" beside the email code. - Added a team working-hours calendar (
TeamWorkCalendarSection) that browses by week or longer period, filters to one member or the whole team, and rolls telemetry up per member (TeamWorkMemberBucket,TeamWorkPeriod,WorkTelemetryRollupGranularity). - Telemetry now records the exact engaged stretches within a day (
DailyWorkSegment,segments) and every individual prompt timestamp (promptTimes), instead of only a first-to-last span, so the timeline shows real gaps rather than one filled bar. - Added file-backed persistence for the agenda, company-context and execution-metrics documents (
FileBackedStores), so those panes work against local files rather than requiring Supabase. - Added a headless telemetry view in the CLI and two inspection scripts (
scripts/inspect-transcript-prompt.swift,scripts/render-working-hours-chart.swift).
Changed
- Agenda items expose
researchRoleas an alias ofrole, with a matching initializer, so the older research-oriented call sites keep compiling against the renamed agenda model. - Model pricing data was reworked in
Pricing.swift; per-day, per-model token rows now feed the digest sums.
Fixed
- Long-term wins text and the daily-wins writer no longer emit the stray epistolary wrapper in some paths; forecast and digest rollups were corrected alongside the new segment data.
Compatibility requirements
- Persisted telemetry documents gain
segmentsandpromptTimes. Days written by an earlier release have neither, so their timelines render from the span only until they are recomputed.
Operator actions required
- Google sign-in must be enabled as a provider in the Supabase project before the new button can succeed.
0.2.9 - 2026-06-17
Reconstructed from git diff v0.2.8 v0.2.9 because the release was published without notes.
Added
- Added "Continue with GitHub" sign-in through Supabase OAuth using the PKCE authorization-code flow. The consent screen opens in an
ASWebAuthenticationSession; GoTrue redirects back toswiatowid://auth-callback?code=…, which the app exchanges for a session (PKCE,oauthAuthorizeURL-predecessorgithubAuthorizeURL,exchangeCodeForSession).
Security-relevant changes
- The OAuth flow is PKCE-only: a 64-byte random verifier stays on the device and only its SHA-256 challenge is sent to the authorize endpoint, so an intercepted authorization code is not redeemable on its own.
Configuration changes
- The application bundle now registers the custom URL scheme
swiatowid(CFBundleURLTypes,CFBundleURLNameai.wisent.swiatowid.oauth).
Operator actions required
- Enable GitHub as a provider in the Supabase project and register
swiatowid://auth-callbackas an allowed redirect URL, otherwise the button fails at the provider.
Known limitations
- Cancelling the provider sheet is deliberately silent — no error is shown — which is indistinguishable from a provider that never opened.
0.2.8 - 2026-06-16
Reconstructed from git diff v0.2.7 v0.2.8 because the release was published without notes.
Changed
- Every proactive Slack post now passes through one shared engagement gate (
EngagementGate) instead of each surface deciding for itself. The daily operating check-in, the daily wins digest, the weekly and monthly recaps and the morning welcome DM all reward their previous post by how it landed and then ask the shared model whether that kind of message is still worth sending; one the team keeps ignoring goes quiet. - Per-member digests on a shared channel are scored only against that member's own messages, matched by the
*<name> —prefix, so a teammate's post no longer rewards someone else's digest. - A suppressed check-in no longer burns its once-per-day marker: the stored signature is cleared so the message can be reconsidered later.
Known limitations
- The gate reads the last 20 channel messages to judge reception, so a busy channel can push the relevant post out of the window and score it as silence.
0.2.7 - 2026-06-16
Reconstructed from git diff v0.2.6 v0.2.7 because the release was published without notes.
Added
- Added a persisted learner over post topics (
ContentEngagementStore), the content counterpart to the existing tone learner. Each topic keeps an exponential-moving-average score, is rewarded by how the post landed, and is suppressed once it falls below the floor. - Answers posted in a public team channel now use their own prompt (
questionReply,questionAnswerSystemPrompt): sourced, explicit about what it does not know, and required to name the item, owner or status it relies on. Private DMs keep the terser reply. Public channels are recognized by the Slack channel-id prefixesCandG.
Fixed
- Fixed the suggestion spam in which the same unanswered topic was re-raised roughly ten times. Suggestions now pick one still-engaging topic and stay silent when everything worth raising has been ignored into suppression, and exploration is confined to eligible topics so a suppressed topic is never re-raised by chance.
- Fixed approval escalations resetting on unrelated metadata refreshes. The escalation fingerprint is now the stable
source|ididentity rather than the churningdetail/statusfields, so a refreshed brief item no longer restarts the escalation ladder and re-spams the channel. - Fixed the tone learner reading the wrong prior message: it now scores the last message the bot actually posted in the resolved window.
0.2.6 - 2026-06-16
Reconstructed from git diff v0.2.4 v0.2.6 because the release was published without notes. v0.2.5 was never published.
Added
- Added weekly and monthly long-term wins recaps (
AutoGoalsStore+LongTerm.postLongTermWinsIfNeeded,LongTermWinsWriter). Each posts once per completed period, gated on a key stored in the goals document and persisted only after a successful Slack post, and reuses the existing 180-second extract loop rather than adding a scheduler. - Added token and implied-cost telemetry unified across Claude, Codex and Kimi (
TokenExtractor,TokenTelemetry,DailyModelTokens), with cache writes and cache reads priced separately. - Added published-list-price reference data in one place (
Pricing,TokenRate). A model with no known rate is reported uncosted rather than silently priced at zero; a superseded model version is priced at its family's current rate and flagged as approximate. - Added period work-texture insights (
PeriodInsights) and day-texture insights for the daily digest (DigestInsights), including comparison against the previous period and against the member's usual rhythm for that weekday. - Added per-goal effort attribution (
GoalEffort): prompts and time from the goal's own session, tokens and cost from that session's token stream.
Changed
- The daily-wins note is written in the product voice and then deterministically stripped of the greeting and sign-off the on-device model insists on adding (
stripEpistolary), because the note is already rendered under its own Slack header.
Known limitations
- Kimi sessions are reported without per-goal token or cost attribution. Their token file is keyed separately and their user turns carry no timestamps, so attribution would not be sound; the value is left absent rather than estimated.
- Implied cost is a list-price estimate, not billed spend.
0.2.4 - 2026-06-16
Reconstructed from git diff v0.2.3 v0.2.4 because the release was published without notes.
Fixed
- Fixed duplicated goals. When the model emitted
startGoalwith the same title on several turns of one session instead ofcontinueCurrent, identical goals stacked up.GoalLifecycle.dedupnow collapses goals sharing a (session, title): it keeps the earliest start, the latest activity, marks the goaldoneif any copy finished, and preserves an already-set announce flag so a transition still posts at most once.
0.2.3 - 2026-06-16
Reconstructed from git diff v0.2.2 v0.2.3 because the release was published without notes.
Added
- Added Kimi Code as a third coding-agent source alongside Claude Code and Codex. Sessions under
~/.kimi-code/user-historyare indexed, so Kimi work feeds goals, telemetry and search; Kimi appears in the agent dock with its own icon and can be resumed from a transcript row; statistics attribute its work by name. - Provider dispatch was extracted into
TranscriptIndexer.candidates(forRoot:)with one walker per on-disk layout, so a further provider is added there instead of by growing the scan function.
Fixed
- Fixed sessions from providers without per-message timestamps being indexed once and then skipped forever. Undated turns now receive monotonically increasing stamps, so the extractor's
timestamp > cursorfilter advances turn by turn exactly as it does for dated Claude and Codex transcripts.
Compatibility requirements
TranscriptSourcegained akimicase. Persisted transcript data written by this release is not readable by an earlier one.
Known limitations
- The Kimi history file records only the user's own prompts, with no assistant turns and no timestamps, so a Kimi session's last activity falls back to the file modification time.
0.2.2 - 2026-06-16
Reconstructed from git diff v0.2.1 v0.2.2 because the release was published without notes.
Fixed
- Fixed goal extraction aborting mid-run. Unpaced rapid on-device classify calls tripped the Foundation Models rate limit and killed the whole run; calls are now paced 700 ms apart, keeping them under the cap.
- Fixed the extraction order so today's sessions are processed before the backfill. Entries are now walked most-recent-first, so a long backfill no longer delays current goals, and a failure part-way through leaves the recent work already persisted.
0.2.1 - 2026-06-16
Reconstructed from git diff v0.2.0 v0.2.1 because the release was published without notes.
Fixed
- Fixed the shipped application aborting immediately at launch with dyld
Library not loaded: @rpath/Sparkle.framework. The bundler now embedsSparkle.frameworkinContents/Frameworks, gives the executable an rpath that resolves it, and code-signs the embedded framework with the same identity as the application.
Operator actions required
- Reinstall from this release.
v0.2.0cannot launch, so it cannot update itself through Sparkle.
0.2.0 - 2026-06-16
Reconstructed from git diff v0.1.0 v0.2.0 (58 files) because the release was published without notes. v0.1.0 itself is a draft and was never published, so this is the first section with a published artifact.
Added — intent-level goals
- Added a goals layer that answers "what did the user set out to accomplish", extracted on device by Apple Foundation Models rather than inferred from a working-directory name (
AutoGoal,GoalStatus,GoalIntentExtractor,GoalIntentRules). It is persisted per organization and triggered manually; the existing heuristic per-project work tracker is untouched and continues to work independently. - Added the Goals workspace pane with an explicit "Extract goals" action, and a headless
swt-cligoals harness, which is the only way to exercise the extractor without the SwiftUI app.
Added — work telemetry
- Added per-member work telemetry computed on the member's own machine from their own recent transcripts: working span, prompt volume, prompt length, engaged time and session count (
DailyWork,WorkTelemetryStore,WorkTelemetryPane), persisted per user. - Added a work forecast that predicts a member's start and end of day from their own history (
WorkForecast). Too little data yields an explicit "not enough data", never a guess. - Added a headless telemetry harness in
swt-clifor the same reason as the goals harness.
Added — organization-scoped configuration
- Slack and Ultrareach (iMessage) configuration moved into Supabase per organization (
OrgIntegrationStore,IntegrationsSettingsView), replacing device-local dotfiles. Owners and admins can edit; everyone else sees the values read-only. - Message routing contacts became a per-organization list (
OrgContact), replacing two hardcoded named recipients.
Added — evolving voice
- Added an explicit set of voice registers over one constant identity and one constant set of hard rules (
SwiatowidTone,SwiatowidVoice), plus a persisted learner that rewards the last used register by how the post landed and picks the next one (ToneEvolutionStore). The chosen register applies to every outbound surface, not only the channel that produced the feedback. - Added the orchestrator suggestions path and its model responder, and a Kimi agent runner and model router entry.
Changed
- The research-specific agenda was generalized into a product-neutral agenda:
ResearchAgenda*types, stores, seeds, migrations and panes were renamed toAgenda*, and the pane hierarchy moved accordingly.
Compatibility requirements
- Integration settings are read from Supabase from this release on. An organization that has not filled in the Integrations settings screen has no Slack or Ultrareach configuration, even if the previous device-local files are still present.
- Goals and telemetry require macOS 26.0 for the on-device model. On macOS 14 and 15 both layers stay empty rather than falling back to a cloud model.
Operator actions required
- Re-enter the Slack and Ultrareach configuration under Settings → Integrations for each organization, and define its routing contacts.
Known limitations
- Goal extraction is manual in this release; there is no background loop.
- Neither goals nor telemetry has a SwiftUI-testable path, which is why both ship with a headless CLI harness.