Skip to content

v4.4.0

Choose a tag to compare

@github-actions github-actions released this 20 Jul 07:44

Added

  • obscura_research gains a background deep-research mode: three new tools, an unattended
    multi-round crawl, and a per-run report (ADR-0060).

    obscura_research_start(objective, topics, topic, …) launches a job that runs INSIDE the MCP
    server process for up to 30 minutes, the way a human researcher iterates on a hard question —
    each round reuses deepResearch whole, then a
    local model (generateLeads, zero-shot, the same qwen3.5:4b-q4_K_M expand model curation
    already uses for recall tasks) proposes typed next queries (subtopic/related/analogy/
    application) anchored to the stated objective rather than the seed topics' literal wording. The
    call itself returns in milliseconds: the MCP transport's 60s tools/call wall is client-side and
    unavoidable for one call (ADR-0057 §5), so depth now lives entirely off the wire instead of
    costing an agent round-trip per increment, the way the prior persist:true+excludeHashes loop
    did (still supported, unchanged). Poll progress with obscura_research_status, stop early with
    obscura_research_stop; only one job runs at a time — the same fan-out ban risk ADR-0057 §6
    measured live applies at greater scale to an unattended run. Every round persists to
    RESEARCH/<topic>/ as it finishes (a killed process loses only the round in flight), and a run
    report lands in RESEARCH/<topic>/runs/<timestamp>.md on every exit path — including an
    "Unexplored leads" section naming application/improvement ideas the job never got to chase —
    ready for /vkm-research <topic> to consolidate. New, optional env knobs:
    OBSCURA_DEEP_ROUND_MS (default 100000) and OBSCURA_DEEP_PACE_MS (default 15000). This is the
    "background continuation" mechanism ADR-0057's fourth addendum explicitly declined, pending "a
    use case [that] ever needs progress with no caller ever returning" — the trigger it named,
    firing. packages/obscura-web 326/326 tests, no regressions.

  • Static analysis now gates the ~32k LOC of shipped JavaScript. New root ESLint 10 flat
    config (@eslint/js recommended + tuned no-unused-vars, no-shadow, and the type-aware
    promise rules no-floating-promises / await-thenable / no-misused-promises via
    typescript-eslint), plus a CI-gated tsc checkJs pass (tsconfig.checkjs.json) over
    shipped src — tests stay covered by ESLint's type-aware rules through
    tsconfig.eslint.json; skill templates are excluded because their optional deps only exist
    in the user's env. Run with npm run lint / npm run typecheck; both wired into the
    ci / lint job, and node:test runners are allowed via allowForKnownSafeCalls instead of
    a blanket disable. The first sweep took 861 ESLint + 424 checkJs findings to zero and fixed
    real defects along the way: vkm-doctor's CLI main() ran unawaited (a crash died as an
    unhandled rejection instead of a clean non-zero exit), a no-op await on the synchronous
    NodeSDK.start(), a dozen wrapper throws that discarded the original error (now
    { cause }), async HTTP handlers passed where a void listener is expected (now guarded with
    a .catch backstop), dead stores, and producer JSDoc contracts narrower than the values they
    actually return (e.g. curatePage's undocumented relevance/reason fields).

  • A safe self-update path for installed skill/subagent templates, plus an opt-in version
    check (ADR-0061).
    npx @vkmikc/create-vkm-kit --check-update reports the installed vs.
    npm-latest version and a plan for every managed file under ~/.claude/skills/ and
    ~/.claude/agents/, without writing anything or ever failing on a network error (offline
    degrades to an honest "skipped" line). --update applies that plan: new/missing/kit-only-changed
    files install, a file you edited locally is left alone and reported as conflict (only
    --force overwrites it, and it says so — that DISCARDS the local edit), and both accept
    --dry-run to preview with zero writes. The classification is three-way (template vs. the
    sidecar's recorded install-time hash vs. what's on disk now — chezmoi's
    source/target/destination model), because the sidecar already recorded the ancestor hash for
    uninstall's benefit; that is what makes "you edited this" and "the kit changed this"
    distinguishable instead of both looking like "disk differs from template." v1 covers the
    hash-guarded asset layer only — managed rule blocks and MCP registrations still need a normal
    installer re-run.

  • Structure gate for the shipped skill templates, against Anthropic's published
    skill-authoring checklist (ADR-0061).
    New test/skill-structure.test.mjs enforces, over all
    four shipped skills: SKILL.md body ≤500 lines, a ## Contents heading on any reference file
    over 100 lines, one-level reference nesting (no new relative .md-to-.md link inside a
    skill, past a small named baseline of four pre-existing ones), forward-slash link paths, and a
    valid non-branded frontmatter name. vkm-design's eight reference files over 100 lines gained
    a Contents heading as part of landing this gate.

  • Drift gate for the repo's own Cursor memory rule. The committed
    .cursor/rules/obsidian-memory.mdc is fresh-install output of the installer
    (installRules(["cursor"], "es")), not an agents-manifest.yaml artifact — so no check
    covered it and it silently kept the pre-rename obsidian-memory:start/end sentinels and
    create-obsidian-memory branding across the vkm-kit rename (ADR-0041). sync-agents.ts now
    renders the fresh-install output (the newly exported CURSOR_RULE_FRONTMATTER +
    memoryRulesBlock("es") through the real mergeManagedBlock) and byte-compares it under
    --check (already in CI), failing with a "rerun the generator: npm run sync-agents" hint;
    write mode regenerates the file. The committed copy is regenerated to the current block, and a
    package test pins generator output ≡ gate expectation so the two can never diverge.

Changed

  • CONTRIBUTING.md's SemVer section now describes the kit, not the v1 prompt, and adds an
    explicit post-4.x versioning policy.
    The MAJOR/MINOR/PATCH definitions still spoke of
    "prompt section numbers"; they are rewritten in terms of the installed contract (CLI flags,
    MCP tools, vault layout/hooks), and the new policy freezes majors except for unavoidable
    contract breaks — batched into one planned major with its migration doc. README links the
    policy from "Más · More".

  • Repo face: a social-preview card, and the measured claims now name their substrate.
    docs/assets/social-preview.png (1280×640, on the hero.svg design language) gives GitHub's
    social preview and link unfurls a real card instead of a cropped avatar. The READMEs'
    token-economy paragraph now states what those numbers are measured against — a fixed labelled
    corpus and a deterministic embedder, i.e. reproducible regression floors, not leaderboard
    claims — and the hybrid-memory chip marks semantic search as the local opt-in it is. The code
    already said both (embeddings.py, ci.yml comments); the front page now matches it.

Fixed

  • The repo's own .cursor/rules/obsidian-memory.mdc no longer ships the pre-rename block. The
    committed dogfooding artifact (not generated by sync-agentsagents-manifest.yaml never
    listed it) still carried v2 branding: obsidian-memory:start/end sentinels, "Bloque gestionado
    por create-obsidian-memory", the (obsidian-memory-kit) frontmatter description, and it
    predated the RESEARCH/ and discipline sections. Regenerated with the current generator
    (installRules, fresh-install path), asserting the ADR-0041 legacy-sentinel migration produces
    the identical managed block. The cursor frontmatter (CURSOR_RULE_FRONTMATTER in
    rules-merge.mjs, the drift gate's single source) now writes the (vkm-kit) description for
    new installs too — the last v2-branded string the installer still emitted.

  • go.mod module path matches the repo slug. The module still declared
    github.com/Vahlame/obsidian-memory-kit, so importing or go install-ing the daemon by its
    real path (github.com/Vahlame/create-vkm-kit/cmd/obsidian-memoryd) failed — latent only
    because the installer builds locally. agent.toml's [daemon].module mirror is updated to
    match.

  • release.yml no longer reports success when npm publish silently skipped. The npm-publish
    job soft-exited (exit 0) when the NPM_TOKEN secret was missing, so the workflow went green
    while npm stayed behind — this shipped 4.2.0 and 4.3.0 to GitHub without their npm counterparts
    until someone noticed. Both publish steps now emit a ::error:: annotation and fail the job
    when the token is absent; fork runs were already excluded by the repository guard, so the hard
    fail only ever fires where publishing is actually expected.

  • Stale obsidian-memory-kit URLs swept from every functional link. LICENSE.md (root + the
    package mirrors via license:sync), SECURITY.md's source-verification step and this
    changelog's compare/release link definitions still pointed at Vahlame/obsidian-memory-kit;
    the GitHub redirect masks it today, but a redirect dies the day the old slug is re-registered.
    Historical mentions of the rename stay as written.

  • License labeling stopped implying plain MIT. Both README badges now read
    "MIT-derived + attribution (non-OSI)" and the License sections state explicitly that the
    mandatory visible-attribution clause is outside the OSI open-source definition — matching what
    package.json already declares ("license": "SEE LICENSE IN LICENSE.md"). Labeling only; the
    license terms are unchanged.

  • vkm-downloads was missing from both README "What's inside" tables despite shipping since
    4.3.0 — added, including its install mode (opt-in --downloads, deliberately not part of
    --full because it writes to disk).

  • ci / links no longer flakes red on github.com HTTP/2 resets. lychee fired up to 128
    concurrent requests; github.com answers such bursts with HTTP/2 GOAWAY/protocol errors — one
    run failed 10 links that all returned 200 when probed individually, half of them in files the
    PR never touched. The token/API fallback can't help (it's a transport error, not a 429), so the
    job now caps --max-concurrency 32 and retries with backoff (--max-retries 4,
    --retry-wait-time 2). De-flaking then unmasked two deterministic 404s in this changelog's own
    link definitions — v3.6.0 was never tagged — fixed by dropping the dead [3.6.0] definition,
    retargeting [3.7.0] to v3.5.0...v3.7.0, and moving [Unreleased] off its stale v3.12.0
    base onto v4.3.0.

  • ci / secrets-scan no longer fails on a third-party licence server. gitleaks-action v3
    validates a licence against gitleaks.io on every run; while that endpoint answered "No server is
    currently available" the job failed with "missing gitleaks license" on a leak-free tree — that is
    what turned PRs #67 and #68 red. The gitleaks binary itself is MIT and needs no licence, so CI
    installs v8.30.1 directly (sha256-verified, retry on download) and runs the same full-history
    scan (236 commits, no leaks, exit 0).