Skip to content

Releases: Kibertum/tausik-core

TAUSIK v1.8.0 — a shared knowledge base, and the end of the server-side session

Choose a tag to compare

@Yumash Yumash released this 04 Aug 14:09

A shared knowledge base — one file per person, not per project

This is what 1.8 is for. A pattern, a dead end, a convention used to live inside one project and die with it; the next project started from zero, and anyone working for three clients learned the same thing three times.

tausik memory add pattern "Title" "Body" --global   # into the shared store
tausik search "query"                               # reads both
  • --global puts knowledge in the shared store or fails saying so — it never falls back into the project quietly.
  • Search and the session-start knowledge block read the shared store alongside the project's own.
  • The store has a backup, and the backup stays on this machine.
  • An older TAUSIK meeting a store newer than its schema refuses rather than guessing at the format.
  • Rows no longer record which client they came from: origin_project holds a basename@fingerprint label instead of the originating project's absolute root.

It is written WITHOUT redaction — which is exactly why it does not leave this machine, and exactly why TAUSIK_HOME is now validated (breaking change 6).

The end of the server-side session

"Session" was two things — work continuity and agent context hygiene — and separating them closed a silent failure: an absent session no longer means unlimited capacity, so the 200-call gate stopped quietly waving work through. A handoff no longer requires an open session.

Team state travels in git

Tasks, decisions and memory export to a readable tausik/ tree, ride along in the repository, and come back with tausik sync. A teammate who clones the repo gets the project's history, not an empty database.


Six breaking changes follow, each with a migration.

Read before upgrading: What changed in 1.8 · Что изменилось в 1.8

Full changelog: CHANGELOG.md · CHANGELOG.ru.md — 165 entries.

Breaking changes

1. The classifier no longer decides what gets published: decide NEVER publishes on its own.
Before, tausik decide ran the text through a classifier, and if it judged the decision "general", the page went to Notion automatically. Now the author decides visibility, always — this project by default, --global for the local shared store, and outward only via tausik brain move --to-brain <id>. The defect was not that the heuristic sometimes chose wrong, but that it was making the publication decision at all; it had already sent six internal decisions outward, among them the decision to cancel the 2.0 plan.
Migration: nothing to do. Publish explicitly if you relied on decisions appearing by themselves. Already-published pages are untouched.

2. The shared knowledge store moved from ~/.tausik/ to ~/.tausik-knowledge/.
~/.tausik was a defect: project discovery walks UP the tree looking for exactly the name .tausik, so a store in the home directory captured discovery for everything beneath it.
Migration: none — the store is adopted from the old address on first use, copied rather than moved, and nothing in your home directory is deleted. One exception: if TAUSIK_HOME is set, adoption does not run at all and the move is yours.

3. Config trust tiers: the project tier may only TIGHTEN.
.tausik/config.json could switch enforcement OFF, and that file travels with the repository — a bypass anyone who clones it inherits without choosing it. A project-scope setting may now make enforcement stricter, never looser.
Migration: move any loosening into the user tier (TAUSIK_USER_CONFIG, or the managed tier).

4. Verify receipt schema: v1/v2 → v3 (schema v44).
A verify run can now be PRESENTED rather than searched for.
Migration: receipts are re-issued on the next run; anything parsing receipts must read v3.

5. A verify run with no declared scope no longer certifies anything.
tausik verify --task X, run before the task declared its relevant_files, recorded a green against an empty file set — and that green stayed usable for the whole cache TTL. Two properties combined into a hole: gate_runner SKIPS the scoped gates when no files are declared, and compute_files_hash([]) returns a stable empty marker no edit ever moves. So verify → edit → task done passed QG-2 on a green taken before the edit. The absence of coverage was converting itself into proof of coverage.
Migration: tausik verify --task <slug> --relevant-files <paths...>. A full-suite tausik verify without --task is unaffected.

6. TAUSIK_HOME is validated, and some locations are now refused.
A network path (UNC, or a mapped/mounted network volume) and a cloud-sync directory (OneDrive including "OneDrive - Company", Dropbox, Google Drive, iCloud, Yandex.Disk, the macOS ~/Library/CloudStorage/ tree) are REFUSED. A store git is ALREADY TRACKING is refused; a store merely inside a git work tree is not — it gets a .gitignore of its own. The store is written WITHOUT redaction, and the whole justification on record is that it never leaves this machine — a property of a DIRECTORY, which this variable names. ~/OneDrive is inside your home, so "it is in my home" stayed true while the conclusion drawn from it did not.
Migration: point TAUSIK_HOME at a local directory outside any synced tree; tausik knowledge export <dir> from the old location first, then TAUSIK_HOME=<new> tausik knowledge restore <dir>.

Also new

  • Verify run handles. tausik verify --task <slug> prints <run_id>.<nonce>; task done --verify-handle presents it instead of the server searching for a fresh row. Single-use, one-hour lifetime, validated against the live files and the live gate config. Refusals now say what is actually wrong ("the files this receipt covers have changed") rather than "cache miss".
  • Notion is optional in fact, not just by flag.
  • The Rule 5 checklist gate reads evidence written BELOW its heading, not only beside it. It had been reporting "no acceptance criterion names a test" over checklists that named several.

Verification

Check Result
Full suite, Windows, exclusive local run 6955 passed, 0 failed
Full suite, Linux (development pipeline) 6839 passed, 0 failed
Matrix: ubuntu / windows / macOS × Python 3.11–3.13 green
Full lane including slow tests green
bandit -r scripts/ zero HIGH
ruff check scripts/ tests/ bootstrap/ clean on 0.15.12 and 0.16.1

Four defects were found by the act of publishing and fixed before this release. Three were of one kind — code deciding the SHAPE of a path by asking which OS was reading it; the sharpest sat in the UNC refusal that the store's whole "it never leaves this machine" argument rests on, and it only worked on Windows. The fourth was the lint gate itself, which enforced a rule set it had never named, inherited from the linter's default — until that default changed.

Note on the tree: of this project's own tausik/ state projection the mirror carries only gates.json, which is shipped gate configuration the test suite reads. The task and decision history stays on the development remote.

v1.7.0 — OpenCode support, one canonical MCP tree, output economy

Choose a tag to compare

@Yumash Yumash released this 16 Jul 20:49

OpenCode support — and the reason it took three tasks to ship one IDE.

A user's OpenCode host died with ConfigInvalidError and ERR_MODULE_NOT_FOUND.
The config that killed it was not written by TAUSIK: no such code existed. It was
written by an agent, by hand, because our docs listed OpenCode as a supported
platform while bootstrap had no branch for it. The agent found "supported" and
found nothing configured, and closed the gap by guessing — inventing a tools.qg0
object (the key is boolean-only) and a plugin importing @opencode-ai/plugin (a
package that does not exist at that version).

A support claim with no code behind it is not a harmless inaccuracy. It is an
instruction to improvise.
So this release ships the code first and the claim last.

What is verified, and what is not. Everything below is covered by the test suite
(both lanes green: 4694 full / 4578 fast) and by tausik doctor. Three things are
not verified and are stated here rather than left for a user to discover:
the QG-0 plugin has never run under a real Bun/OpenCode host — its behaviour is
exercised under Node against a faked Bun shell; the OPENCODE_DIR / OPENCODE_BIN_PATH
environment variables are taken from OpenCode's documented behaviour and were not
confirmed against a live build (auto-detection does not depend on them — the
.opencode/ directory check does); and the -32601 log noise is confirmed gone by
code inspection and tests, not by watching a restarted host's log. Live OpenCode
validation is deferred to QA. The compression figure caveman reports for itself
(~65%) is likewise their measurement, not ours.

Added

  • OpenCode is a scaffolded IDE. bootstrap.py --ide opencode writes
    opencode.json (MCP servers + the instructions key), installs the rules at
    .opencode/tausik-rules.md, and deploys command stubs. Every path in the MCP
    command is absolute: OpenCode expands no ${workspaceFolder} — copying Kilo's
    portable paths would have produced a config that points at a literal directory
    named ${workspaceFolder}.

  • QG-0 enforcement for OpenCode (.opencode/plugins/tausik-qg0.js, note the
    plural — a singular plugin/ directory never loads and never says so). The
    plugin implements tool.execute.before and refuses write/edit/apply_patch
    when no TAUSIK task is active, the same contract as Claude Code's PreToolUse
    hook. It has zero imports — not even a type-only one — because the import is
    what killed the user's host. Types come from JSDoc; it runs with nothing
    installed.

    Its active-task verdict is cached against a signature of the DB files
    (tausik.db + the WAL), not against a bare TTL: task done moves the WAL, so a
    cached "allow" cannot outlive the task that justified it. The cache may only ever
    err toward strictness. When the CLI cannot be reached the gate fails open — a
    broken CLI must not brick an editor — but never in silence: it warns that QG-0 is
    degraded and names TAUSIK_HOOK_FAIL_SECURE=1 as the way to invert the policy.

  • tausik doctor validates OpenCode installs. It catches the three ways this
    host fails quietly: an object under tools (fatal to the host at startup), a
    missing or singular-directory plugin (enforcement simply absent), and
    instructions pointing at a file that does not exist (rules simply never load).
    It also refuses to report "writes are refused" unless the CLI wrapper the plugin
    queries actually exists — a guarantee doctor cannot verify is a guarantee it will
    not make.

  • Guard: an IDE cannot claim to be scaffolded without a dispatch branch
    (tests/test_scaffold_dispatch_backed.py). Parsed from the AST, so a comment
    naming an IDE cannot satisfy it. Without this, --ide <name> would copy the
    skills, print Done!, configure nothing, and exit 0 — the silent no-op that
    started this whole story.

  • Output-economy mode (output_mode: caveman, opt-in). Orthogonal to context_tier:
    the tier compresses the input rules TAUSIK injects, this compresses the agent's
    output. When enabled, bootstrap appends a short directive — inspired by the
    caveman skill — telling the agent to answer
    in terse prose while keeping code, commands, tool output and error messages byte-exact,
    and acceptance-criteria evidence, decisions and SPEC/ADAPT full (future agents parse
    those). Shipped as our own rule via build_full_body, so it reaches all five IDEs from
    one source — deliberately not through caveman's own installer, whose Claude-Code
    hooks and settings.json merge would collide with TAUSIK's SessionStart hook and its
    ownership of that file. The directive is length-capped and guarded: it is injected every
    session, so a bloated directive would cost more input than the terse output saves.
    Default off; a bad value falls back to off without crashing. caveman's own
    "~65% reduction" is their figure — unmeasured in TAUSIK's harness, so not restated as
    ours. tausik doctor reports coexistence when the real caveman skill is also installed,
    and warns if a caveman hook is wired into the .claude/settings.json TAUSIK manages.

Changed

  • OPENCODE_DIR no longer detects as Codex. They are different hosts with
    different configs; an OpenCode session was being handed .codex/ paths that
    OpenCode never reads.

  • Rules reach OpenCode through instructions, not AGENTS.md. OpenCode
    resolves AGENTS.md first-matching-file-wins, so a user's own file would shadow
    ours forever; instructions files are merged with it instead. Consequently
    --ide opencode generates no AGENTS.md — it would put identical rules in the
    context twice.

  • The platform table is now enforced against the code. The Scaffolded column
    in docs/*/model-providers.md is checked against SCAFFOLD_IDES; the table and
    the code cannot drift apart in either direction.

Removed

  • harness/cursor/mcp/ — 19 files, deleted. It was a byte-for-byte copy of
    harness/claude/mcp/; diff -r across the whole tree returned exactly one
    difference, a single word in one docstring. Nothing generated it. It was kept in
    sync by hand, and a project convention existed telling agents to keep doing so.

    The danger was never the duplication itself — it was the precedence. copy_mcp
    prefers harness/<ide>/mcp/ over the canonical tree when it exists, so the first
    time anyone patched only the Claude copy, Cursor users would have silently kept
    running the old server, and no test would have noticed: each mirror passed its own
    checks in isolation.

    Cursor now receives the canonical tree through the fallback that Kilo, Qwen and
    OpenCode have always used. Verified equivalent: copy_mcp hands all three servers
    to all five IDEs. A guard (tests/test_mcp_single_canonical_tree.py) refuses any
    file under harness/<ide>/mcp/ that is byte-identical to its canonical counterpart
    — an IDE may ship a genuinely different server, it may not ship a copy of ours.

Fixed

  • MCP servers answer prompts/list and resources/list instead of -32601.
    The error was harmless — tools worked fine — but it filled the host log with a
    message that reads exactly like a dead server, and it did: a user reported the
    MCP as broken when it was not. All three canonical servers (project,
    codebase-rag, brain) now return an empty list — and since copy_mcp hands that
    one tree to every IDE, every host gets the fix.

  • opencode.rules_path can no longer escape the project. .tausik/config.json
    travels with a repository, so a tampered one would have turned the next bootstrap
    into an arbitrary-file-write. Escaping, absolute and drive-qualified overrides are
    refused — loudly, and without crashing: the containment check itself used to raise
    (os.path.commonpath throws on a foreign Windows drive), and a crash is not a guard.

  • Bootstrap no longer reports success on a config that cannot start. The project
    that triggered this whole release still holds the config that killed it — a tools
    object, and a plugin under the singular .opencode/plugin/. Re-running bootstrap
    merged our stanzas in beside them and printed a cheerful "Done!", while OpenCode went
    on refusing to boot for exactly the same reason as before. TAUSIK does not delete
    those (they are the user's file), but it now says plainly what is fatal and what to
    remove, and tausik doctor fails on the same conditions.

  • The QG-0 plugin can actually be upgraded. Plugin resolution preferred the copy
    already installed in the project, which exists after the first bootstrap — so every
    later run resolved source == destination and skipped the copy. A user upgrading TAUSIK
    to get a fixed gate would have run bootstrap, seen it succeed, and kept running the
    broken one: the enforcement artifact was the single file an upgrade could never reach.
    The library copy now wins.

  • tools as a list or a string is caught too. The doctor check only inspected
    objects, so "tools": ["qg0"] sailed past it and doctor printed "valid — no tools
    object"
    : an OK that affirmed the very thing that was broken.

  • The docs no longer name an npm package that does not exist.
    @anthropic-ai/opencode was never real (OpenCode is SST's opencode-ai). Docs
    that name a nonexistent package teach agents to invent module names by analogy —
    which is precisely how @opencode-ai/plugin@local ended up in a user's project.
    A guard now fails the build if any doc puts a bogus package on an install line.

v1.5.8 — /start can't freeze (session_open watchdog)

Choose a tag to compare

@Yumash Yumash released this 06 Jul 13:28

Reliability release. /start could freeze forever on "Generating…" on large projects.

Fixed

  • tausik_session_open (the /start Phase-1 compound RPC) could hang the whole session. Its 5 sub-calls were wrapped only in try/except, which catches exceptions but not a blocked call — so a sub-op that hangs rather than raises (a DB write contending with sibling MCP servers, a self_check subprocess wedged past its timeout, a pathologically large repo) froze the envelope and the IDE sat on "Generating…" indefinitely. Each sub-call now runs under a daemon-thread watchdog (_section_with_timeout, 6s) that returns {"error":"<section> timed out after 6s"} for the wedged section instead of blocking. /start degrades to a visible, self-diagnosing dashboard and the error names the culprit. Cross-thread DB use is safe (conn check_same_thread=False, busy_timeout=5000). Applied to claude + cursor handlers.

v1.5.7 — Windows cp1252 decode fix

Choose a tag to compare

@Yumash Yumash released this 06 Jul 11:49

Field-fix release. v1.5.6 hardened the encode side (writing Cyrillic / ✓ output on Windows); v1.5.7 fixes the decode side — hooks and gates that read TAUSIK CLI or git output back.

Fixed

  • SessionStart hook (and other CLI readers) crashed on Windows when captured output contained Cyrillic. subprocess.run(..., text=True) decoded child stdout with the OS locale codec (cp1252 on a typical RU Windows), which chokes on UTF-8 Cyrillic bytes (0x81 is undefined in cp1252). The reader thread raised UnicodeDecodeError, leaving result.stdout=None, then .strip() raised AttributeError outside the caught tuple — so the whole hook aborted with a traceback and no session context was injected (framework "silently broken" on Cyrillic-content projects). Every text=True subprocess reader of CLI/git output now passes encoding="utf-8", errors="replace" — 12 call sites across session_start, _common, auto_format, task_done_verify, session_metrics, check_docs, project_cli_extra, project_cli_renar, pytest_test_count, service_session, verify_git_diff. The last two also affect the task done / verify gates on repos with Cyrillic filenames or git user.name.

Full suite: 4313 passed / 12 skipped.

v1.5.6 — Kilo + Windows/Unicode fine-tune

Choose a tag to compare

@Yumash Yumash released this 20 Jun 08:19

[1.5.6] — 2026-06-19

Fine-tune release from a live Kilo Code + z.ai (GLM) field test. The structural
root was three drifted IDE lists; they are now two named constants.

Fixed

  • Kilo-only installs got "no scripts dir found" from the CLI. The wrapper's
    IDE-discovery loop hardcoded claude cursor qwen windsurf codex — no kilo
    so bootstrap --ide kilo produced a .tausik/tausik that couldn't find
    .kilo/scripts. The loop is now injected from bootstrap_config.IDE_DIRS
    (the single source of truth) into the wrapper template at install time via an
    __IDE_LIST__ placeholder; add an IDE to IDE_DIRS and every consumer picks
    it up. --ide all and the --ide argparse choices now derive from a sibling
    SCAFFOLD_IDES constant. (P0/P4)
  • Windows UnicodeEncodeError on Cyrillic / ✓ output. Layered UTF-8 hardening:
    the CLI wrapper exports PYTHONUTF8=1; every hook runs via python -X utf8
    (one injection point in the hook-command builder, covering all hooks); and the
    standalone entry points — bootstrap.py and all MCP servers — call
    fix_stdio_encoding() at startup. Note: PYTHONUTF8/-X utf8 fix the locale
    default but do not override an explicit PYTHONIOENCODING; the runtime
    reconfigure does. (P1)
  • Skill/rules paths resolved to .claude under Kilo/Qwen. The runtime IDE
    layer (ide_utils) only knew claude/cursor/windsurf/codex, so under a
    Kilo-only install detect_ide() fell back to claude and skill install /
    SessionStart profile rebuild targeted .claude instead of .kilo. qwen
    (.qwen/QWEN.md) and kilo (.kilo/AGENTS.md) are now registered and
    detected via their project dirs + TAUSIK_IDE. (Env-var auto-detection for
    kilo/qwen is intentionally deferred until verified on a live build.) (P5)

Added

  • task quick --ac/--acceptance. Quick-create a task with its acceptance
    criteria in one command, so it is QG-0-ready (goal + AC) without a follow-up
    task update. Blank/whitespace AC is ignored — QG-0 is unchanged. Exposed on
    the tausik_task_quick MCP tool as well. (P2)
  • tausik doctor validates the Kilo MCP config. When a .kilo//.kilocode/
    install is present, doctor checks that kilo.jsonc / mcp.json parse (JSONC
    tolerated), carry a tausik-project mcp stanza with a command array, and
    that the referenced server.py resolves (${workspaceFolder} expanded). Each
    finding tells you to re-bootstrap and restart Kilo. Silent for non-Kilo
    projects. (P3)

Internal

  • Guard tests lock the IDE single-source invariant (SCAFFOLD_IDES ⊆ IDE_DIRS,
    argparse choices and --ide all derive from the constants, no hardcoded IDE
    list literal in bootstrap/) and the Unicode-stdio fixes (wrapper, hooks, MCP
    servers, bootstrap).

TAUSIK v1.5.5 — Kilo Code + z.ai (GLM)

Choose a tag to compare

@Yumash Yumash released this 19 Jun 10:15

Added — Kilo Code + z.ai (GLM) first-class support

  • --ide kilo bootstrap target. bootstrap.py --ide kilo re-exposes the
    TAUSIK MCP server inside Kilo Code (VSCode addon + CLI). The MCP stanza is
    written to both known Kilo config paths — .kilo/kilo.jsonc and
    .kilocode/mcp.json — so it works across Kilo versions (Decision #120). Format
    is Kilo-native (mcp key, command as an array, type: local, enabled);
    existing servers are merged, not overwritten; re-runs are idempotent. Override
    the target paths via .tausik/config.json kilo.config_paths.
  • Model profiles as data — z.ai GLM routing with no code change (Decision #119).
    New scripts/model_profiles.py maps vendor families (claude, glm) ×
    capability ranks → concrete model ids, overridable/extendable in
    .tausik/config.json model_profiles.families. suggest_model(family=…) and
    the task-start banner now recommend within the active model's family: a
    z.ai GLM session (Anthropic-compatible endpoint → transcript reads glm-*)
    routes to GLM models and gets correct under/over-powered verdicts. Optional
    model_profiles.default_family pins the family when detection is unavailable.
  • Provider registry (scripts/providers/) abstracting runtime/IDE detection
    (claude/cursor/kilo/qwen). Kilo reads the active model from KILO_MODEL /
    .kilo config; Claude delegates to the existing transcript parser.
  • Docs: Kilo + z.ai (+ RU mirror) — setup, model
    switching, secret hygiene; architecture two-axis (runtime × model) table.

Changed — rename-proof generated configs

  • Generated MCP configs and Claude hooks no longer embed absolute project paths,
    so renaming the project folder no longer breaks the framework. In-project
    paths use the host's workspace variable — ${CLAUDE_PROJECT_DIR:-.} (Claude
    .mcp.json), ${CLAUDE_PROJECT_DIR} (Claude hooks), ${workspaceFolder}
    (Cursor, Kilo); paths outside the project (system venv, external lib) stay
    absolute. Shared helper bootstrap/bootstrap_paths.py. Qwen Code is unchanged
    (no workspace variable in its config format) — tracked as a follow-up.

Fixed

  • Provider scaffold rewritten: removed a syntactically broken claude.py,
    inconsistent registration, and a model_routing import that silently nulled
    active-model detection.

TAUSIK v1.5.3

Choose a tag to compare

@Yumash Yumash released this 15 Jun 11:02

Hardening release on the road to 2.0. Windows fixes (CLI wrapper, RAG reserved-name walk), RENAR adoption surfaced on the landing, 4348 tests. Clean public snapshot; full development history lives in the private mirror.