Releases

synlynk Changelog

Stay up to date with new features, improvements, and fixes to the multi-agent coordination kernel.

All notable changes to synlynk are documented here.

Format follows Keep a Changelog. Versioning follows Semantic Versioning.


Unreleased

Added

  • synlynk agent add <name> to retroactively onboard a newly available CLI agent on $PATH, generating its directive file, writing its role fence, wiring workgroup_agents / agent_slots / roles, and seeding a capability baseline. Fixes #277.
  • Lazy daily housekeeping on the first synlynk exec of a new calendar day, detecting new PATH agents, re-probing onboarded agents for drift, repairing directive fences, and recording last_housekeeping_date. Fixes #277.

Fixed

  • synlynk migrate false-positive MigrationImportError on idempotent re-runs (#276): the loud-fail check treated INSERT OR IGNORE with rowcount == 0 as a hard failure whenever a non-empty source landed zero new rows. On a project that had already been migrated, natural-key collisions (especially roadmap_arcs.version UNIQUE) correctly no-op the insert, so re-import / --recover raised MigrationImportError: 0 rows inserted … roadmap_arcs (N parsed/attempted, 0 inserted) even when every expected row was already present. _migrate_import() now checks natural keys before insert (memory_entries.section, roadmap_arcs.version, roadmap_phases(arc_version, phase_title), cost fingerprint, devlog author+date+title, todo gh_issue already set) and only fails loud when zero rows were inserted and not all attempted rows were already present. Genuine 0-of-N write failures still raise with the same error message prefix.
  • Dispatch auto-PR branch detection (#280): _finalize_completed_worktree_job() re-derives the worktree's actual current branch via git branch --show-current instead of trusting the pre-recorded dispatch/<agent>/<job_id> name. When an agent commits on a custom branch (the encouraged human-readable pattern), push and gh pr create --head now target that branch; the job record is updated so synlynk jobs reports the real name. Detached HEAD falls back to the recorded branch without erroring.
  • synlynk probe now clears HARNESS_VERSION_DRIFT alerts for the specific agent it just re-probed, so the warning disappears once the recorded installed_version matches the live binary again. Fixes #281.
v0.12.02026-07-15

Release pitch: the operational backbone gets provably reliable and provably accounted for — dispatched jobs finish their own git steps, a 5th zero-cost local agent joins the fleet, story routing gets real capability+quota+cost scoring with a fleet batch scheduler, and every dollar synlynk reports is now either structurally sourced or visibly flagged as an estimate.

Added

Measurement Ledger Hardening — Phase 1 + Phase 2 + display layer (epic #210, PRs #236/#241/#242/#244/#245/#246/#252/#256/#257/#264/#266/#267)

Phase 1 — provenance-tagged cost tracking (PR #236):

  • cost_entries gained explicit provenance columns: cost_source TEXT NOT NULL (actual | estimated_token_rate | estimated_tshirt | estimated_manual | legacy_unknown, no default — every INSERT must pass it explicitly) and estimate_basis TEXT. Migration rebuilds the table and backfills historical rows as legacy_unknown.
  • _insert_cost_row() (synlynk/db.py) is now the sole sanctioned writer to cost_entries, replacing four independently-drifting direct-SQL write sites in dispatch.py, jobs.py (×2), and support_engineer.py. Upserts by job_id when present. Enforced by a call-site audit test that fails the suite if any other file writes to cost_entries directly.
  • extract_tokens() now tags a .basis (regex_pair | total_split | none) distinguishing a real per-field token extraction from an 80/20 heuristic guess.
  • .synlynk/model_rates.json (scaffolded by synlynk init) is now the source of truth for per-model rates and billing_mode, replacing a hardcoded table; falls back to hardcoded rates on missing/invalid file.
  • New 3-tier t-shirt-size token fallback (_estimate_tshirt_tokens()) for surfaces with no real token count: story's estimated_tokens column → historical average from cost_entries (same discipline+phase, ≥3 samples) → fixed conservative default.
  • synlynk cost log — manually log a cost row for native/unwrapped PM or brainstorming sessions with no CLI token data, tagged estimated_manual.
  • Cost coverage closed across every surface identified in the design spec's audit: dispatch_agent()'s exec wrapper (no longer gated on in_tokens > 0), jobs.py's reconcile and daemon-reconcile paths, cmd_launch(), and support_engineer.py's investigation runs. synlynk release, synlynk probe, and synlynk doctor audited and confirmed correctly out of ledger scope.
  • check_budgets() gained a dedicated sub-line surfacing failed-job placeholder estimates separately from the headline spend total. costs.md and budget parsers now tolerate [est] /[legacy] /~ prefixes.
  • New "Cost Capture Protocol" section in CLAUDE.md.
  • [failed job] marker fix: dispatch.py's zero-token-failure cost label now prepends (not appends) the marker so it survives update_costs()'s 20-character command truncation, restoring check_budgets()'s failed-job sub-line to live code.

Phase 2 — structured-output token adapters, one per dispatch CLI (PRs #244, #252, #256, #257): replaces the 80/20 heuristic split with a real per-field structured-JSON extraction path for each vendor CLI — Codex, Claude, Agy (Gemini), and Grok all shipped, closing epic #210's adapter scope.

Display layer (PRs #264, #266): Vizor's Effort & Cost tab now visually flags estimated-vs-measured cost rows; synlynk status gained a RATES line (and JSON rates_updated_at key) showing when the model rate table was last updated, warning ⚠ never updated when no rate file exists.

Design spec: docs/superpowers/specs/2026-07-13-measurement-ledger-hardening-design.md. Roadmap arc + epic #210 marked shipped (PR #267). Deferred follow-ups filed as issues, out of scope for this release: #260 (Savings Ledger), #261 (dispatch-path unification), #262 (surface consolidation), #263 (stage constants staleness).

Local Agent — 5th dispatch agent, zero-cost on-device inference (PRs #200/#204/#205/#207/#208/#209)

  • local joins claude/codex/agy/grok as a dispatchable agent, running as an aider CLI subprocess against an on-device oMLX OpenAI-compatible endpoint — zero per-token cost.
  • Capability envelope seeding + concurrency guard so local starts with a conservative starter whitelist that self-widens with verified results.
  • Real-hardware opt-in pytest tier (tests/test_local_agent_hardware.py) exercises actual Aider+oMLX end-to-end, correctly skipped when no local hardware is running.
  • Capability-matrix taxonomy worked example + blog post documenting the integration.

Capability Matrix Hardening — 3-stage routing engine + fleet batch scheduler (epic #137, PRs #139/#140/#141/#147/#148/#150/#151/#152/#154/#156)

  • _best_agent_for_story() now scores candidates across three real stages: weighted capability score (VERIFIER tier, dead-signal handling, pr_review_cycles/verified_by_ci signals), a hard quota-headroom gate (agent_quotas table across 5h/hourly/daily/weekly/monthly windows, degraded-mode fallback when quota signal is missing), and a cost tie-break (cheaper model wins when top scores are within 0.15).
  • New synlynk/scheduler.py: stories.priority/readiness columns, synlynk story ready/draft gate, fleet-level in-batch headroom accounting (story N in a batch sees story 1..N-1's projected spend), retry/reassignment capped at 2 attempts, synlynk schedule [--execute] [--max-stories N] CLI.
  • GOVERNS seven-stage vocabulary rollout replaces the old CYCLES/CYCLE_COLOURS naming across the capability taxonomy and HUD.
  • Capability tag enum enforcement + taxonomy reference doc; cycle_capability row dedup migration fix.
  • Deferred v2 (reset-timing-aware bin-packing, persistent quota-blocking history, GOVERNS-aware readiness gate) tracked as a goal, gated on 30 days of v1 production data (deadline 2026-08-10) rather than scoped into stories now.

Job Lifecycle Ground-Truth Verification (#126, #127, #128, #129, PRs #130/#131/#132/#133/#135)

  • dispatch_agent() creates a dedicated git worktree per dispatched job (worktrees/<job_id>, branch dispatch/<agent>/<job_id>) instead of sharing the invoking shell's cwd — concurrent dispatches no longer collide.
  • _reconcile_jobs() cross-checks git state when a job's exit sentinel is missing, instead of treating an ambiguous exit as automatic failure; new "failed_unverified" status flags "inspect before discarding."
  • files_touched is real (via git diff --name-only <merge-base> HEAD + git status --short --porcelain), no longer hardcoded to [].
  • cmd_migrate() prints the resolved DB_PATH and fails loud with MigrationImportError on a 0-row import from a non-empty source, instead of a silent green banner.

Vizor

  • Architect Map v2 (PR #167): replaces the static tube-map SVG with a live force-directed graph of workspace repos and typed cross-repo edges, a side drawer (path/stack/GitHub/dispatch/Gantt-jump/active-dream-count), and an IDE-style file-tree sub-view.
  • Business Goals Panel (PR #153): surfaces goals/stories rollups in the HUD.
  • __init__.py re-modularized a second pass — 11 focused modules extracted (synlynk/db.py, jobs.py, dispatch.py, context.py, sentinel.py, scheduler.py, etc.), no more single-file monolith (PR #180).

Fixed

Dispatch git-finalization reliability chain (#182/#184/#185/#189/#190/#191/#196/#198, PRs #186/#187/#192/#193/#194/#195/#199/#201)

  • Dispatched agents (Codex/Agy) frequently completed real, tested work but didn't reliably finish their own git steps (commit/push/PR). synlynk now performs git finalization itself once, gated on a job's running→terminal transition (idempotent by construction) — stages everything except a hard-exclusion list, commits, pushes, opens a PR via gh pr create if none exists.
  • Borrowed-worktree completions attributed via origin/<branch> state instead of being misread as zero-work.
  • HARNESS_INTERNAL_TIMEOUT jobs now auto-retry (cap 2) instead of landing as a dead failure.
  • A job that raced its own disk writes and landed failed with 0 touched is re-inspected once and reclassified failed_unverified rather than staying permanently stale.
  • Cost accounting no longer bypasses the per-model rate table in 3 places (including a hardcoded gemini-2.5-pro $0 bug); local gets an explicit $0.0 override regardless of model version.
  • Capability router now filters on canonical discipline, not the legacy engg_domain column.
  • Daemon queue launch unified through dispatch_agent() so worktree/preflight/permission-flags/concurrency-guard logic isn't duplicated across two divergent paths.
  • Harness no longer misreports completed jobs as FAILED with fabricated token counts.

Misc dispatch/CI hardening (PRs #163/#164/#165/#171/#173/#238/#240)

  • Codex sandbox gets --add-dir <git-common-dir> so it can write git refs inside a worktree.
  • dispatch --help's agent list now derives from AGENT_CAPABILITY_BASELINES instead of a stale hardcoded list.
  • Stall-killer generalized to detect harness-internal timeouts and checks remote branch activity before hard-failing a silent job.
  • 3 baseline CI flakes isolated from runner environment state; Python 3.8 compat fix for a tuple[str, str] annotation.
  • dispatch --context-mode full now warns when used on a task that's already self-contained.

v0.11.02026-07-05

Release pitch: synlynk v0.11.0 is the Agent Ecosystem Operational Layer — every dispatch now carries permissions and recovery paths, your terminal shows a live fleet of agents in real time, and the full workflow discipline is baked into every agent directive file at init.

Added

Agent Autonomy Bridge (BS-12, PR #119)

  • synlynk dispatch --grant <perm> --revoke <perm> — per-task permission overrides; role defaults in .synlynk/config.json map 12 roles (pm, review, implement, test, css, infra, etc.) to capability tiers. Resolved set translates to --allowedTools (Claude), --approval-policy (Codex), or a ## Permissions context header (Agy).
  • synlynk configure agent <name> [--flag k=v] [--env K=V] [--network-dep host:port] — write per-project harness overrides to .agents/<agent>.json; dispatch_agent() merges at call time: baseline → per-project overrides → per-task grant/revoke.
  • synlynk jobs --stalled — list jobs with HANDOFF_PENDING sentinel (set when a job accumulates STALL_NO_OUTPUT, FLATLINE, or QUOTA_EXHAUSTED). Shows job ID, agent, failure sentinel, elapsed time, and recommended next agent.
  • synlynk jobs handoff <job_id> [--to <agent>] — transfer a stalled job to a new agent; appends ## Handoff Note to the job context file, increments handoff_count, updates previous_agents (JSON array), launches new dispatch with full context, clears HANDOFF_PENDING.
  • synlynk doctor TC-5 — scans each directive file for all 6 required SOP section headers; warns (non-blocking) if any are absent. Interactive fix wizard runs after each TC failure with structured fix paths (TC-1–5) and an "I'm stuck" escape that assembles failure context and dispatches Claude for conversational diagnosis.
  • synlynk sync --repair-sops — re-injects missing SOP sections into directive files without touching existing harness fence content. Idempotent.
  • 6 SOP blocks written into CLAUDE.md, GEMINI.md, AGENTS.md, and GROK.md at synlynk init and synlynk sync time: PR Review Discipline · Brainstorm-First Policy · Design → Plan → Build Sequence · Capability-Based Task Allocation · Cost Visibility · Repo Hygiene.
  • daemon_jobs schema additions: handoff_count INTEGER DEFAULT 0, previous_agents TEXT (JSON array). Migration applied automatically on first access.

Live Job Observatory (BS-13, PR #117)

  • synlynk watch --live — fullscreen live job board: all running/recent jobs with agent, status, elapsed time, cost, and output tail; auto-refreshes every 3s; Ctrl-C to exit.
  • Vizor Observatory tab — fifth tab in synlynk viz browser dashboard: real-time job fleet table (JS polling), per-agent status badges, cost rollup, job output drawer.

Vizor Efficiency Enrichment (BS-22, PRs #113, #118)

  • R/W/T budget bars — per-agent card shows Read, Write, Test utilisation as percentage of TIER1_CAPACITY.
  • Cycle × Agent capability matrix6 × 4 table (dream/plan/work/ship/maintain/engage × Claude/Agy/Codex/Grok) with full/partial/none badges (cap-full, cap-partial, cap-none CSS classes).
  • Per-agent radar hexagon SVGs — 80×80px SVG radar on each agent card; 6-axis polygon filled at 30% opacity with agent theme colour; axis score maps full→1.0, partial→0.5, none→0.0.

Ecosystem Status + Capacity (BS-16, PR #110)

  • synlynk status — terminal platform health: harness compliance table, agent availability, budget pulse (R/W/T capacity bars per agent), 6-cycle capability matrix.
  • synlynk status --json — machine-readable ecosystem snapshot consumed by Vizor as its live data contract.
  • Three dispatch modes: eco (respects R/W/T budget gates), daily-grind (default), perf (no budget gates).
  • Three new _preflight_dispatch() gates: CAPACITY_EXCEEDED_INPUT, CAPACITY_EXCEEDED_OUTPUT, TOOL_PRESSURE.
  • New state.db tables: harness_status, cycle_capability; probe command extended to seed Tier 1 capacity baselines.
  • synlynk/status.py new module; HarnessSnapshot dataclass in hud.py.

Modularisation (chore, PRs #103–#109)

  • Extracted synlynk/__init__.py (11,268L) into five focused modules: synlynk/probe.py, synlynk/sentinel.py, synlynk/upgrade.py, synlynk/dispatch.py, synlynk/_constants.py. __init__.py reduced to ~1,500L of orchestration and CLI surface.

Fixed

TC-2 dispatch fix arc (PRs #114–#116)

  • Fixed false-positive TC-2 failures caused by Agy dispatch_flags baseline including --non-interactive (valid for Agy but flagged as invalid by harness validator). Corrected per-agent flag baseline maps.
  • Fixed _run_tc2 seeding invalid flags into the passed list on first scan, blocking all subsequent Agy dispatches.
  • synlynk logs now shows exit summary + TC-2 preflight gate result per dispatch.

BS-12 review fixes

  • --repair-sops now merges missing SOP blocks into existing harness fence body instead of replacing the entire fence.
  • TC-5 result wired into all_passed in cmd_doctor; doctor now exits non-zero when SOPs are missing.
  • Handoff note included in handoff_task sent to new agent (was reading context before append).
  • TC-5 fix menu scoped to agents with missing sections only (was firing for all agents in loop).
  • --flag KEY (boolean flag without =) in configure agent now uses partition instead of crashing with ValueError.

BS-22 review fixes

  • Removed is_placeholder short-circuit in SVG circles matrix that contradicted the new text capability matrix.
  • CSS class cap-{support} now normalised to lowercase; prevents unstyled cells from mixed-case DB values.
  • Removed unreachable dead-code fallback block in get_capability_level().

Changed

- `synlynk doctor` interactive fix wizard replaces silent print-and-exit after TC failures. - `_check_job_stall()` now also writes `HANDOFF_PENDING` sentinel on STALL_NO_OUTPUT / FLATLINE / QUOTA_EXHAUSTED. - `dispatch_agent()` merge layer: baseline → `.agents/.json` harness overrides → per-call `--grant`/`--revoke`.
v0.10.02026-07-03

Release pitch: synlynk v0.10.0 is the Developer Preview — install it via pipx, set up your workspace in 60 seconds with the terminal wizard, and get a live browser dashboard that shows exactly what your agent team is doing.

Added

FTUE + Onboarding

  • synlynk init --wizard — FTUE typeform-style TUI wizard (6 screens: home harness detection, workspace topology, skills scan, agent fleet, role assignment, launch cheat sheet). Mandatory Phase 0 silent scan; writes workspace config, state.db, and role blocks into each agent's directive file. Ctrl-C before completion leaves no state.
  • synlynk scan — re-runnable repo analysis: detects topology (single/mono/multi), fingerprints stack per repo/package via 14 file-presence heuristics, parses CLAUDE.md/GEMINI.md/AGENTS.md, maps to workspace in state.db, regenerates structured context.md. Flags: --refresh, --add <path>, --remove <path>, --dry-run.
  • synlynk launch — FTUE task picker TUI with 6-cycle SDLC view (Dream · Plan · Work · Ship · Maintain · Engage); 12 scan-triggered launch templates (3 core + 9 stack-aware); dispatch preview screen; synlynk open replaces old synlynk launch <agent> for direct agent open. (BS-19, PR #94)
  • synlynk roles — print current agent role table from .synlynk/config.json; synlynk init and synlynk doctor now generate per-agent directive role blocks (## Your Role in CLAUDE.md, GEMINI.md, AGENTS.md). (BS-12a, PR #95)

State + Migration

  • synlynk migrate — one-shot atomic import of project-docs/ markdown into state.db (8 steps: import → copy to .synlynk/project-docs/git rm.gitignore → sentinel → commit). After migration, every DB write immediately mirrors to .synlynk/project-docs/ as a local backup (write-through). Flags: --dry-run, --recover (re-import from backup after DB loss), --setup-dr (configure cloud-synced DR folder).
  • synlynk memory add / synlynk devlog append — write memory entries and devlog sessions to state.db with immediate flat-file write-through.
  • 5 new state.db tables: memory_entries, roadmap_arcs, roadmap_phases, cost_entries, devlog_entries; gh_issue column on stories.
  • DR sync — configurable dr_sync_path in .synlynk/config.json; every write-through copy is also synced to a cloud-synced local folder (iCloud/GDrive/OneDrive). No OAuth, no new deps.

Deep Scan

  • synlynk scan (deep mode) — 6-stage pipeline: repo fingerprint, dependency graph, test coverage ratio, doc coverage, CI health, churn density. Stage Cards TUI with progress indicators; scan fences written to state.db; synlynk launch templates upgrade automatically from scan signal data. 6 new scan fields: test_ratio, readme_word_count, has_ci, has_docs, has_type_hints, has_orm. (BS-20, PR #96)

Daily-Driver Commands

  • synlynk jobs --summary <id> — after every job closes, print structured summary: files touched, exit status, cost, tokens, duration; append to .synlynk/logs/<job_id>.summary; readable via synlynk jobs --summary <id>. (PR #97)
  • synlynk release — Ship cycle stub: bump VERSION, generate CHANGELOG entry from merged stories since last tag, write blog post stub in docs/blog/; --dry-run previews without writing. (PR #98)
  • synlynk status --platform — infrastructure health view: harness compliance (last probe, any DRIFT sentinels), agent availability table (installed/version/TC status), budget pulse (daily/weekly burn rate). (PR #99)

Browser Dashboard

  • synlynk viz — 5-view local browser dashboard generated from state.db, served at http://localhost:8721. Views: Gantt (accordion drill-down, stage bars, pencil notes), User Journeys (split-pane, docs/journeys/*.md), Architect Map (tube map SVG from vizor-tube.json), Effort & Cost (SVG bar charts), Efficiency (agent report cards + sentinel timeline). Sticky note system: POST /noteviz-notes.json → injected into generate_context() (visual annotation → AI context loop). Live JS polling + browser notifications. Zero new deps. (BS-21, PR #101)

Packaging

  • pipx packagingpyproject.toml with [project.scripts] entry point; VERSION is the single source of truth in synlynk/__init__.py (pyproject.toml reads it via dynamic attr). Install via pipx install git+https://github.com/nikhilsoman/synlynk.
  • _detect_install_type() — detects pipx vs pip vs script install; synlynk upgrade routes to pipx upgrade synlynk when installed via pipx.

Changed

- **`generate_context()`** routes to `_generate_context_from_db()` when `.synlynk/.synlynk_migrated` sentinel is present; reads from state.db (top story, recent devlog entries, recent memory sections). - **`install.sh`** derives VERSION dynamically from `synlynk/__init__.py` instead of hardcoding. - **Python requirement** raised from 3.8+ to 3.9+. - **Refactor:** `main()` extracted to `synlynk/cli.py`; data-layer functions extracted to `synlynk/db.py`. Single-file `bin/synlynk.py` is now a thin dispatcher. - README fully overhauled: pipx install, badge strip, wizard-first 60-second quickstart, state.db architecture, all new commands documented.

Tests

  • 747 tests (up from 588 at v0.9.8); 28 new migrate tests, 28 launch/FTUE tests, 21 Vizor tests, 7 packaging tests, 40 deep-scan tests, full E2E round-trips.

v0.9.82026-06-27

Added

- **`synlynk exit`** — reverse all synlynk onboarding: strips managed sections from tracked instruction files (CLAUDE.md, GEMINI.md, etc.), removes `.agents/` profiles and `.synlynk/` directory, writes `SYNLYNK_HANDOFF.md` with re-init instructions. Dry-run by default; `--confirm` to execute. `--remove-docs` optionally removes `project-docs/`. - **`synlynk repair`** — exit + immediate re-init from captured config (agents, mode, org, repo, docs-dir). Dry-run by default; `--confirm` to execute. - **`synlynk sync`** — propagate updated synlynk artifacts (instruction file sections, missing `.agents/` profiles) to an existing repo without full re-init. Dry-run by default; `--confirm` to execute. - **`_strip_synlynk_section(path, marker_style)`** internal helper — removes synlynk-managed block from any instruction file; handles html/hash/none marker styles; leaves surrounding user content intact.

Changed

- VERSION bumped `0.9.7 → 0.9.8`
v0.9.72026-06-26

Added

- **Grok as a first-class fourth agent peer** alongside claude/agy/codex across all synlynk subsystems - `AGENT_CAPABILITY_BASELINES["grok"]` — cli, non_interactive_flags (`-p`), prompt_via_arg, dispatch_flags (`--always-approve`), roles (builder/architect), strengths - `AGENT_DISCOVERY_DEFAULTS["grok"]` — discovery path `~/.grok` - `_probe_model_version` — `grok -v` probe + `grok-[\w.-]+` version pattern - `GROK.md` template — identity (`Co-Authored-By: Grok `), branch prefixes (`feat/grok/`, `fix/grok/`), standard session/worktree/live-issues sections, `synlynk:start/end` markers - `_INSTRUCTION_TARGETS` + `_MARKER_STYLE_FOR_TOOL` entries for GROK.md - Init wizard: GROK.md in `trio_content` + `_agent_guards`; `agent_slots` default expanded to four agents; `--agents` default updated to `claude,agy,codex,grok` - `_inject_grok_rules()` — prepends `--rules GROK.md` for all grok exec calls; adds `--rules .synlynk/context.md` in headless (`-p`) mode; silently skips missing files - `dispatch_agent()` — `--always-approve` → `--permission-mode bypassPermissions` fallback via agent profile `always_approve_unsupported`; `--output-format json` for grok headless dispatch - `extract_tokens()` — nested `usage.input_tokens/output_tokens` pattern for Grok JSON output - `extract_model_version()` — tier-2 path via `.agents/grok.json` `"model"` field - `GROK.md` written to the synlynk repo itself (100 lines, markers bookending) - 15 new tests covering all registration, instruction file, init wizard, exec injection, dispatch, and token/model extraction paths

Fixed

- Stale time-sensitive fixture in `test_collect_capability_drop_returns_finding` — hardcoded 2026-06-21 timestamps replaced with `datetime.now(timezone.utc)`-relative values
v0.9.32026-06-23

Added

- `SynlynkDaemon` class — subclasses `WatchDaemon` to add an embedded HTTP server thread on `localhost:27471` and persistent job dispatch on every poll tick; double-fork daemonization inherited from `WatchDaemon`; separate pidfile `.synlynk/daemon.pid` and log `.synlynk/daemon.log` - `daemon_jobs` table in `state.db` — persistent job queue with `priority` (1–10), `depends_on` (JSON array of job IDs), and full status lifecycle `queued → running → done | failed` - `_reconcile_daemon_jobs()` — reaps finished child processes using `os.waitpid(WNOHANG)` (zombie-safe), reads `.exit` files for exit codes, updates `status`/`exit_code`/`completed_at` in state.db - `_dispatch_ready_jobs(max_parallel)` — launches queued jobs respecting concurrency cap and dependency chains; propagates `failed` status to downstream dependents immediately; commits per-job for crash-safe restart semantics - HTTP API on `localhost:27471` — 10 endpoints: `GET /context`, `GET /status`, `GET /jobs`, `GET /jobs/`, `POST /dispatch`, `GET /stories`, `GET /stories/`, `GET /capability`, `GET /sentinel`, `POST /checkpoint`; `_ReuseAddrHTTPServer` subclass prevents `Address already in use` on rapid restart; `threading.Lock` guards concurrent `generate_context()` calls - `synlynk daemon start|stop|status|restart` CLI command - `synlynk daemon --install-service` — writes and activates platform service unit: macOS: `~/Library/LaunchAgents/com.synlynk.daemon.plist` via `launchctl load -w`; Linux: `~/.config/systemd/user/synlynk-daemon.service` via `systemctl --user enable --now`; Fallback: `@reboot` crontab entry - `synlynk daemon --uninstall-service` — reverses each platform path; handles `FileNotFoundError` gracefully

Fixed

- Daemon zombie process detection: replaced `os.kill(pid, 0)` with `os.waitpid(WNOHANG)` so exited child processes are properly reaped rather than staying `running` indefinitely - Dependency deadlock: queued jobs whose dependency fails are immediately marked `failed` rather than staying queued forever - Transaction isolation in dispatch: each launched job is committed individually so a crash mid-loop cannot produce duplicate spawns on restart
v0.9.22026-06-22

Added

- `synlynk join` — new member onboarding: seeds a devlog stub for the joining user, regenerates AI context files (CLAUDE.md, GEMINI.md, AGENTS.md) with the joining member's identity, and prints a team digest showing all active members and their recent focus areas - `synlynk team status` — team digest view: lists all members with devlog presence, current story assignments, token budget consumption, and last-active timestamp; reads `project-docs/devlogs/.md` across all contributors - `synlynk decide --panel ` — multi-agent consensus panel: dispatches the panel agents non-interactively with the same decision prompt, collects structured `DECISION:` blocks from each response, computes a consensus position, and optionally writes a signed `Decision` record to `project-docs/decisions/YYYY-MM-DD-.md` with `--record` flag - `--tokens ` flag on `synlynk story create` — set an estimated token budget for a story; stored in new `estimated_tokens` column on the `stories` table - `_seed_devlog(username, root)` helper — writes a devlog stub for the joining user with an initial entry so the devlog file exists and is attributable in team digests from day one - `_generate_ai_context_files(username, root, config)` helper — regenerates CLAUDE.md, GEMINI.md, and AGENTS.md with the joining member's name in the `git config user.name` slot - `_build_team_digest(root)` helper — reads all devlogs from `project-docs/devlogs/`, extracts last-active date and focus summary per member; used by both `join` and `team status` - `_check_upstream_divergence(root)` helper — checks whether the local branch is behind the remote before any write to `project-docs/`; prints a warning with advice to `git pull` if divergence is detected; continues without blocking so offline workflows still function (pull-before-write arbitration)

Fixed

- None in this release
v0.9.12026-06-22

Added

- `--docs-dir ` flag on `synlynk init` — override the default `project-docs/` location for repos that store docs elsewhere (e.g. `--docs-dir docs/project`) - `_docs_dir(root, config)` helper — reads `docs_dir` from `.synlynk/config.json`, falls back to `project-docs/`; used by `exec`, `checkpoint`, `status`, and `init` so every command respects the configured docs location

Fixed

- Installed binary (`~/.synlynk/bin/synlynk`) crashed with `ModuleNotFoundError: No module named 'synlynk'` when invoked outside the source repo after the v0.9.0 package split. Fixed by embedding the package `synlynk/` directory in `~/.synlynk/lib/synlynk/` at install time and prepending `$HOME/.synlynk/lib` to `sys.path` in the installed shim. - `synlynk init` in a repo with existing `project-docs/` overwrote the existing docs with blank templates. Fixed by detecting existing files via `_find_existing_doc()` and migrating their content to the new location (or skipping write if no relocation is needed).
v0.9.02026-06-21

Added

- Scoped dispatch context: `exec` now injects a per-task section (`## Current Task`) with only the relevant plan block instead of the full devlog, reducing context window usage - `## Relevant Files` injected per dispatch from the source map — derived from the task description matched against `source-map.md` symbols - `## How to Verify` contract injected per dispatch — specifies acceptance criteria the agent should validate before declaring the task done - Per-agent prompt framing: Claude, AGY, and Codex each receive a tailored preamble that matches their CLI interaction model (conversational vs. task-oriented vs. non-interactive) - Ed25519 capability rating signing: every `capability_ratings` row is signed with the project key so ratings cannot be forged across project boundaries - Anti-gaming quality cap: `test_count < 3` stories are capped at quality score 5.0 regardless of other signals, preventing artificially inflated ratings for untested work - `synlynk/` package split: all ~5000 lines of application logic moved from `bin/synlynk.py` into `synlynk/__init__.py`; `bin/synlynk.py` becomes a 5-line import shim

Fixed

- `capability_ratings` entries were not being attributed to the correct project when multiple synlynk-managed repos shared the same `~/.synlynk/` directory — Ed25519 project key now scopes all ratings correctly
v0.8.02026-06-21

Added

- `synlynk agent run` — foreground support engineer investigation: collects signals, formats a structured report, and offers to file a GitHub issue or draft a fix PR - Five signal collectors for the support engineer archetype: failing tests, flaky tests, coverage gaps, stale dependencies, open GitHub issues exceeding age threshold - 7-day and 30-day deduplication: signals already filed within the window are suppressed so the agent doesn't file duplicate issues on repeated runs - `synlynk agent --install-cron` — registers a launchd plist (macOS) or systemd timer (Linux) that runs the support engineer agent on a configurable schedule - `.agents/` config directory: `support-engineer.json` defines signal weights, age thresholds, and notification channels per project; read by `synlynk agent run` at startup - GitHub issue filing via `gh issue create` with structured body including signal summary, affected files, and suggested fix skeleton - Draft fix PR creation via `gh pr create` for issues with high-confidence fix candidates
v0.7.02026-06-20

Added

- `synlynk scan` / `synlynk scan --deep` — language-agnostic source scanner: reads file tree, extracts top-level symbols from Python/JS/TS/Go/Rust/Ruby/Java/C/C++ source, writes `source-map.md` and populates `source_symbols` table in `state.db` - `## Source Architecture` section injected into every `exec` context from the cached scan result, giving agents a structural overview without reading individual files - Passive git-HEAD cache: scan results are keyed to the current git HEAD SHA; a re-scan is only triggered when HEAD changes, not on every `exec` call - `synlynk scan --status` — shows last scan timestamp, HEAD SHA, and symbol count without re-scanning - Dual storage: symbols written to both SQLite `source_symbols` table (queryable) and `source-map.md` (human-readable, injected into agent context) - Language detection by file extension with fallback to content heuristics

Fixed

- `synlynk scan` no longer traverses `.git/`, `node_modules/`, or `.synlynk/` directories
v0.6.12026-06-17

Added

- Instruction reach to seven additional IDE/editor targets: Cursor (`.cursor/rules/`), GitHub Copilot (`.github/copilot-instructions.md`), Windsurf (`.windsurfrules`), Cline (`.clinerules`), Aider (`.aider.conf.yml`), Continue (`.continue/config.json`), and Sourcegraph (`.sourcegraph/memory.md`) - SHA manifest (`instructions.json`) tracking the synlynk-managed section hash for each generated file; used for drift detection - Runtime drift detection: `exec` warns if any tracked instruction file's section has been externally modified since last generation - `synlynk instructions status / diff / update / ack` — manage instruction file state - Task status model: 5 states (`active`, `done`, `deferred`, `superseded`, `absorbed`); deferred tasks are included in context with reduced weight; `checkpoint` archives resolved states to a separate section - AGY CLI replaces Gemini CLI throughout: all references to `gemini` updated to `agy` - VERSION synced to GitHub releases (was incorrectly stuck at 0.4.x) - `DB_PATH` centralised to `~/.synlynk/projects//state.db` so the database is shared across worktrees of the same project
v0.6.02026-06-14

Added

- Model version tier-2 probe: `discover_agents()` now probes for Opus/Sonnet/Pro variants in addition to the base model, annotates capability entries with `model_tier` - `synlynk pr check` — validates that the current branch's diff satisfies the story's acceptance criteria before opening a PR; exits non-zero if criteria unmet - `synlynk score attest` — manually attest a story's quality score with a signed reason; appended to `capability_ratings` with `attestation=true` flag - Verifier pipeline output capture: `run --trio` now captures and surfaces the Verifier agent's structured review comment - Tokq `org_domain_tags` capability dimension: stories can be tagged with domain taxonomy labels (`backend/api`, `frontend/ui`, etc.) for cross-project capability aggregation - Constraint propagation: blocking story constraints propagate to child tasks; dispatching a child task for a blocked story emits a warning and requires `--force`
v0.5.02026-06-14

Added

- SQLite WAL state database (`~/.synlynk/projects//state.db`) replacing the flat JSON job store; WAL mode enables concurrent reads from multiple agent processes - Model-aware routing: `dispatch` selects agent by matching story domain tags against `capability_ratings`; no domain match falls back to round-robin - 3D domain taxonomy for capability rating: `(agent, domain, model_tier)` composite key replaces flat per-agent scores - Quality signal hierarchy: test coverage, PR review comments, story completion rate, and task duration all feed the capability score; weights configurable in `.synlynk/config.json` - `synlynk story create ` — create a new story in `state.db` with optional domain, priority, and acceptance criteria - `synlynk story list` — list stories with status, domain, assignee, and capability score - `synlynk score` — print capability score breakdown for all agents across all domains <hr> <div class="changelog-version-header"><span class="changelog-version">v0.4.2</span><span class="changelog-date">2026-06-17</span></div> <h3 class="tag-added">Added</h3> - Task status model (`active` / `done` / `deferred` / `superseded` / `absorbed`) added to the context schema; deferred tasks included in `context.md` with a `[deferred]` prefix - `checkpoint` archives all resolved-state tasks to a `## Resolved Tasks` section rather than deleting them — preserves decision history while keeping the active list clean - Agent instruction templates updated to explain the 5-state model and checkpoint archival <hr> <div class="changelog-version-header"><span class="changelog-version">v0.4.1</span><span class="changelog-date">2026-06-17</span></div> <h3 class="tag-added">Added</h3> - Section marker system: synlynk-managed blocks in instruction files delimited by `<!-- synlynk:start -->` / `<!-- synlynk:end -->` markers so user customisations outside those markers are preserved on regeneration - SHA manifest (`instructions.json`): tracks content hash of the synlynk section in each generated file; used for drift detection - `synlynk instructions status / diff / update / ack` — full CLI for managing instruction file drift - `DB_PATH` centralised: all state now written to `~/.synlynk/projects/<git-root-hash>/` rather than `.synlynk/` within the project, so the database is shared across all worktrees of the same project <h3 class="tag-fixed">Fixed</h3> - `init` no longer regenerates files that already contain a synlynk section — protects user customisations from accidental overwrite <hr> <div class="changelog-version-header"><span class="changelog-version">v0.4.0</span><span class="changelog-date">2026-06-14</span></div> <h3 class="tag-added">Added</h3> - `AGENT_CAPABILITY_BASELINES` — hardcoded capability dict for claude/gemini/codex/agy with `cli`, `non_interactive_flags`, `roles`, and `strengths` per agent - `discover_agents(config)` — probes each known agent CLI with `--version`, returns functional agents with their roles and capabilities; supports per-project path overrides via config - `_static_scan(root)` — reads git log, README, and file tree to produce a structured project context dict (project name, commit count, languages, recent topics) - `_write_informed_skeleton(scan)` — writes project-docs/ first draft using scan results instead of blank placeholders - `_llm_enrich(agent_name, agent_cli, scan)` — opt-in step that calls the best available agent non-interactively to synthesise an informed `roadmap.md` from scan results - `init()` refactored to a 6-step wizard: scan → **Magic Moment 1** (workgroup discovery table showing all detected agents with roles) → doc bootstrap → LLM enrichment offer → cloud nudge → finalise config - `dispatch_agent(agent, task, story_id)` — launches agent CLI in background using `subprocess.Popen(start_new_session=True)`, captures stdout to `.synlynk/logs/<job_id>.log`, writes PID and job metadata to `.synlynk/jobs.json` - `_load_jobs()`, `_save_jobs(jobs)` — read/write `.synlynk/jobs.json` - `_reconcile_jobs()` — probes PIDs of running jobs via `os.kill(pid, 0)` on every startup; marks unreachable PIDs as failed/completed; called as first action in `main()` - `synlynk dispatch <agent> --task <text> [--story <id>]` — **Magic Moment 2**: fire and forget agent dispatch from any shell - `synlynk jobs [--all]` — list running/recent jobs with status, agent, and task - `synlynk logs --job <id> [--tail N]` — tail the log file for a job - `synlynk shell [--story <id>]` — open an interactive agent shell with story context injected - `synlynk launch <agent> [--story <id>]` — interactive launcher that prompts for task before dispatching - `synlynk run --trio <task>` — dispatches the same task to all functional agents in parallel (Architect, Builder, Verifier roles) - ANSI colour helpers (`_BOLD`, `_GREEN`, `_YELLOW`, `_CYAN`, `_DIM`, `_RESET`) for wizard UI <h3 class="tag-fixed">Fixed</h3> - `_reconcile_jobs()`: `PermissionError` from `os.kill(pid, 0)` means the process exists (owned by another user) — no longer crashes the CLI; job correctly stays `running` - `_reconcile_jobs()`: empty `log_file` no longer accidentally reads/deletes an unrelated `.exit` file in the current working directory - `_llm_enrich()`: baselines now indexed by canonical agent name (not CLI binary path), so custom CLI paths still resolve the correct non-interactive flags <h3>Infrastructure</h3> <ul> <li>5 new reconcile/enrich tests; 4 new E2E tests (dispatch, jobs, logs, reconcile startup)</li> <li>188 tests total (up from 140)</li> </ul> <hr> <div class="changelog-version-header"><span class="changelog-version">v0.3.0</span><span class="changelog-date">2026-06-03</span></div> <h3 class="tag-added">Added</h3> - Enriched agent instruction templates: CLAUDE.md, GEMINI.md, AI_INSTRUCTIONS.md now include Live Issues SOP (Sev1/Sev2/Sev3 with RCA doc path pattern), Git Worktree-First Policy, per-agent branch naming and commit trailers, Mid-Session Anti-Amnesia Protocol (Phase 1/2 cadence), Mandatory 4-Doc Discipline, and GitHub Projects v2 GraphQL integration block with parameterizable `PROJECT_ID` - `AGENTS.md` — new Codex agent instruction file, generated at repo root on `synlynk init` - `synlynk init --agents <claude,agy,codex>` — controls which agent files are generated (default: all three). Omit an agent to skip its file - `synlynk init --mode <solo|team>` — writes `project-docs/.synlynk_config.json` with the chosen mode at init time (previously this file had to be created manually) - `synlynk init --org <org>` — stores GitHub org name in `.synlynk/config.json` - `synlynk init --repo <repo>` — stores GitHub repo name in `.synlynk/config.json` - `synlynk init --project-id <id>` — fills GitHub Projects v2 node ID into all generated agent files, replacing the `TODO: PROJECT_ID` placeholder - GEMINI.md includes AGY/Gemini CLI transition note: file is shared by Gemini CLI (until 2026-06-18) and AGY CLI (AntiGravity) thereafter; no migration of the file is needed - `_build_templates(org, repo, project_id)` internal function replaces the static `TEMPLATES` dict and `_SESSION_PROTOCOL` string, enabling parameterized template generation <h3 class="tag-changed">Changed</h3> - `synlynk init` now writes `project-docs/.synlynk_config.json` directly (previously missing from init, requiring manual creation) <hr> <div class="changelog-version-header"><span class="changelog-version">v0.2.1</span><span class="changelog-date">2026-05-17</span></div> <h3 class="tag-fixed">Fixed</h3> - `exec_command()` now returns the child process exit code and `main()` calls `sys.exit()` with it — previously a wrapped command exiting non-zero would cause `synlynk exec` to exit 0, silently swallowing failures - `parse_costs_md()` was reading the wrong column (`parts[6]` = Summary instead of `parts[5]` = Estimated Cost USD), causing `status` and budget checks to always report $0.00 - `install.sh` version corrected from `1.2.0-lite` to `0.2.0` - `conftest.py` fixture schema aligned with real `costs.md` format (6-column) so budget tests exercise the correct parser behavior <h3>Removed</h3> <ul> <li>Dead functions <code>log_telemetry()</code>, <code>extract_tokens()</code>, and <code>update_costs()</code> — superseded by <code>log_telemetry_event()</code> and manual cost tracking; removed to prevent confusion</li> </ul> <h3>Infrastructure</h3> <ul> <li><code>.gitignore</code> expanded to cover <code>.synlynk/</code>, <code>__pycache__/</code>, <code>*.pyc</code>, <code>.DS_Store</code>, <code>test_archive/</code>, <code>test_context_output/</code>, <code>.venv/</code></li> <li><code>project-docs/roadmap.md</code> updated to reflect v0.2.x reality (was stale with v1.2/v1.3/v1.4 references)</li> <li>Test added for exit code propagation (47 tests total)</li> </ul> <hr> <div class="changelog-version-header"><span class="changelog-version">v0.2.0</span><span class="changelog-date">2026-05-17</span></div> <h3 class="tag-added">Added</h3> - `synlynk watch start/stop/status` — background daemon that polls `project-docs/` and regenerates `context.md` on any file change, with configurable interval and debounce - `synlynk checkpoint` — archives completed `[x]` tasks from `todo.md` into the user devlog, refreshes context, and emits a structured telemetry event - `synlynk status` — project state dashboard showing active tasks, last checkpoint, sentinel alerts, budget, and watcher state; `--json` flag for machine-readable output - `synlynk init --force` — overwrite existing template files - `set_state()` — writes `.synlynk/state` and updates terminal title with state icon (`●` watching / `⚡` active / `○` stopped) - Helper functions: `get_username()`, `get_mode()`, `load_config()`, `parse_costs_md()` - `log_telemetry_event()` — structured event logging with `schema_version` and `type` fields - `_check_costs_freshness()` — warns when `costs.md` has not been updated within the current session - Devlog archiving: entries older than 30 days moved to `devlogs/archive/YYYY-MM.md` <h3 class="tag-changed">Changed</h3> - `generate_context()` — now compacts output: excludes completed `[x]` tasks, includes only "In Progress" roadmap rows, injects sentinel alerts at top when present, scoped to last 7 days of devlog - `check_budgets()` — now reads cumulative spend from `costs.md` instead of telemetry; request count sourced from telemetry `type=exec` events - `check_flatline()` — now writes alerts to `.synlynk/sentinel.md` in addition to stdout - `exec_command()` — uses `subprocess.Popen` (no stdout capture) for full TTY interactivity with Claude Code and Gemini CLI - `CLAUDE.md` / `GEMINI.md` templates — include full session protocol: startup checklist, during-session rules, session-end steps - `VERSION` bumped to `0.2.0` <h3 class="tag-fixed">Fixed</h3> - Type hint `str | None` replaced with `Optional[str]` for Python 3.8 compatibility (union syntax requires 3.10+) <h3>Infrastructure</h3> <ul> <li>Added pytest test suite (<code>tests/conftest.py</code> + <code>tests/test_synlynk.py</code>) with 46 tests and <code>project_dir</code> fixture</li> <li>Added GitHub Actions CI workflow (runs pytest on Python 3.8, 3.10, 3.12 on push and PRs)</li> <li>Added <code>LICENSE</code> (MIT), <code>CONTRIBUTING.md</code>, PR template, issue templates</li> </ul> <hr> <div class="changelog-version-header"><span class="changelog-version">v0.1.0</span><span class="changelog-date">2026-05-14</span></div> <p>Initial public release.</p> <h3 class="tag-added">Added</h3> - `synlynk init` — bootstraps `project-docs/` (roadmap, todo, memory, costs, devlogs) and writes `CLAUDE.md`, `GEMINI.md`, `AI_INSTRUCTIONS.md`, `.cursorrules` and `.synlynk/config.json` - `synlynk exec <cmd>` — wraps any AI CLI: injects context, checks budget, logs telemetry, detects flatline loops - `synlynk upgrade` — checks GitHub releases API for newer versions - `generate_context()` — compiles `project-docs/` into `.synlynk/context.md` - `check_flatline()` — detects 3 consecutive failures of the same command - `check_budgets()` — warns at 80% of configured USD/request limits - `log_telemetry()` — rolling JSON log of last 100 exec events - `install.sh` — global installer, adds synlynk to `~/.synlynk/bin/` and PATH </div> </div> </section> </main> <!-- Footer stub --> <footer> <div> <span>© 2026 synlynk · MIT License</span> </div> <div> <a href="https://github.com/nikhilsoman/synlynk" target="_blank" rel="noopener">GitHub</a> <a href="/docs/">Docs</a> <a href="/features/">Features</a> <a href="/blog/">Blog</a> <a href="/changelog/">Changelog</a> <a href="/about/">About</a> <a href="/#waitlist">Waitlist</a> </div> </footer> <script src="/assets/js/carousel.js"></script> <script src="/assets/js/main.js"></script> </body> </html>