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
- Add an opt-in personal NATS relay with scoped device credentials, durable
JetStream replay, retention-gap events, subscription filters, and safe document
previews. See self-hosted setup. The
hubextra is optional; the core CLI remains stdlib-only. Managed service provisioning, entitlement checks, and reconnect/status hardening remain follow-up work. - Synlynk is a neutral control plane that routes coding tasks across AI vendors and local models, then proves the result.
- Ongoing Wave 3: Hosted Teams Server Hub, Cloudflare Tunnel full-duplex daemon, and Dynamic Quota Advisory service.
Added
- feat(db): provider-aware `harness_models` catalog — 3-column primary key `(harness_name, model_id, provider)`, rate-card columns (input/output/cache-read/cache-write/tool-use per Mtok), `complexity_tier`, `max_effort_level`, `context_window_tokens`, `discovered_at` (#2293) - feat(models): `run_model_catalog_discovery()` generalizes live-CLI probing across all registered harnesses (not just Agy), with config-file and curated fallbacks, stale-marking for previously-seen-now-absent models, and a no-op gateway loop ready for future OpenRouter/LiteLLM wiring (#2296) - feat(capability): 24h auto-refresh — `is_model_catalog_stale()` wired into `maybe_trigger_staleness_checks()`'s existing daemon-tick/CLI-startup trigger points, reusing `spawn_staleness_check_thread()` (#2297) - feat(models): `resolve_tier_model()` now reads the live `harness_models` catalog first, falling back to the static seed catalog only on a fresh install; `synlynk dispatch --modelFixed
- fix(daemon): bind root for token refresh, resolving a recurring daemon crash on `_repo_common_dir()` when invoked from a non-root worktree (gh:#2288, #2289)This release closes gh:#2291 — two live dispatch failures this cycle (
grok-code-fast-1and an Agy model id both rejected as unknown) traced back to synlynk's model catalog being a static, hand-maintained list with no periodic refresh and no enforcement that dispatch actually reads a live-validated value. Both failure modes recurred again live during this same release's own PR review dispatches, underscoring the fix.
Added
- feat(local): three-model roster schema supporting `Ornith-1.0-9B-4bit`, `Qwen3.6-27B-4bit`, and `Ternary-Bonsai-2-27B-mlx-2bit` - feat(local): custom `prism-ml` loader availability detection and graceful fallback in `synlynk local doctor` and dispatch flag builder - feat(local): platform RAM prober (`_detect_hardware_tier()`) and `synlynk local doctor --init` tier detection and model recommendation - feat(dispatch): tier-0 zero-trust auto-routing via `synlynk dispatch auto` with health and capability score thresholding - feat(gateway): OpenRouter universal gateway configuration preview in `.synlynk/registry.json` and `synlynk gateway probe` CLI command - feat(docker): local model Orb Stack container image (`docker/Dockerfile.sovereign`, `docker/entrypoint.sh`, `.github/workflows/sovereign-build.yml`)Fixed
- fix(dispatch): isolated local model argument construction to prevent bare model names from overriding oMLX provider configuration - fix(cli): graceful rendering of deferred dispatch job responses - fix(local): live end-to-end dispatch validation on Apple Silicon M3 (116s execution, 0 cost, clean diff)Historical Note (v0.23.0 / v0.24.0 version arc gap): Changes planned across the v0.23.0 and v0.24.0 arcs (Graphify auto-extraction, unified canvas, boardroom governance, and local oMLX fleet) were consolidated directly into v0.25.0. Per this repo's documented Named-Release version gap policy (CLAUDE.md: "Gaps in the version arc... are acceptable — users see public history, not internal planning slots"), gaps in public release history represent internal planning slots and are preserved without retrofitting synthetic entries.
Added
- feat(vizor): modern multi-workspace hub UI and /index.html routing fallback (#1758)Fixed
- fix(vizor): support HEAD requests in WorkspaceRoutingHandler (#1760) - fix(core): guard DB_PATH resolution and daemon polling outside project roots (#1759) - fix: fail dispatch early without role GitHub token (#1753) - fix(core): guard sandbox state migration and mutex-lock vizor render context (#1733, #1750) (#1757) - fix: backfill registry repo_path and inspect daemon install returncode (#1743, #1749) (#1756) - fix: resolve codex config model and git worktree identity slug (#1748, #1742) (#1755)Changed
- docs: update devlog, costs, and memory for Sprint 3 (#1733, #1750) - chore: deduplicate harness SOP sections (#1754) - docs: update devlog, costs, and memory for Sprints 1 and 2 - docs: session checkpoint — LIVE-14 resolution, self-approval finding, PR #1744 audit, 3 tickets filed (#1751) - docs: finalize v0.21.0 release entry and set daily release cadence roadmap - chore(release): bump development version to 0.22.0-devAdded
- feat: Vizor cross-workspace daemon (#1744) - feat(models): first-class model catalog, multi-track quotas, and rolling calibration engine (#1727) - feat(testbed): wire model selection and model tiering into synthetic identities - feat(testbed): Frontier QA Testbed engine and multi-node soak testing framework (#1719) - feat(identity): implement 3-tier identity attribution protocol and whoami CLI (W2-T1.4) - feat(mesh): implement AST mesh sibling worktree collision detector and preemption (W2-T1.3) - feat(jobs): implement distributed task leases and heartbeat un-stranding in state.db (W2-T1.2) - feat(relay): implement P2P relay event bus, WS/NATS framing, and peer forwarding (W2-T1.1) - feat(release): verify full regression matrix, readiness gates, and formalize Wave 1 completion - feat(marketing): verify marketing release ceremony and standalone doc bundles (W1-T3.3) - feat(pm,doctor): implement Ring 3 opportunity radar and architect watchdog health checks (W1-T3.2) - feat(charters): implement living trigger registry and autonomous backlog triage triggers (W1-T3.1) - feat(heal): ship Magic PR Engine via synlynk heal --magic (W1-T2.3) - feat(coldstart): ship Deep Brownfield Ingestion Engine via synlynk init --brownfield (W1-T2.2) - feat(vizor): ship Inside-Out World View Extractor & Concentric Radar UI (W1-T2.1) - feat(handover): sovereign multi-home dynamic handover and drain-to-boundary protocol (Wave 1 Task 1.2) - feat(dispatch): model first-class tripartite dispatch and AST cost tiering (Wave 1 Task 1.1) (#1695)Fixed
- fix(dispatch): cap BEHIND/DIRTY PR-review retry churn and block retries on critical cost inflation (#1741) - fix: retry scalar GitHub write verification (#1740) - fix(models): sync codex model catalog with authenticated CLI config (#1739) - fix(dispatch): enable explicit permission bypass and always-approve for headless grok jobs (#1735)Changed
- docs: checkpoint dedicated OrbStack contributor testbed and upstream LiteLLM PR #42579 - docs: W11 Cloudflare Tunnel full-duplex remote access spec (#1729) - docs: W12 Discord/Herdr full-duplex remote-access bridge spec (#1731) - docs: W10 Grok Bot remote MCP surface spec - docs: record LIVE-13 Grok permission bypass decision and devlog - docs(rca): record LIVE-13 Grok headless dispatch permission bypass RCA - docs: record model catalog and rolling quota calibration completion - docs(devlog): record Frontier QA Testbed implementation and decision - docs(spec): design automated acceptance and multi-node soak testbed via OrbStack VMs and Docker - docs(sop): add TPM(bot) GitHub state synchronization SOP and link all Wave Epics/Issues - docs: update tasklist, devlog, and cost log for Wave 1 Task 1.1 (PR #1695) - chore(release): bump development version to 0.21.0-dev and stamp v0.20.0 in CHANGELOG.mdHighlights
- Visual Workspace Observatory (BS-6 Vizor): Interactive browser dashboard with Product, Logical, and Infra graph views (
synlynk viz). - Workspace Agent Roles & Role Studio: Browser-driven GitHub App role onboarding and SFIA-grounded living charters.
- Adaptive Worktree Lifecycle: Automatic stale worktree detection, blast-radius impact analysis, and safe pruning (
synlynk worktree audit/clean). - Fleet Resilience & State DB Hardening: Fail-closed product identity resolution and crash-recoverable state promotion.
Breaking Changes
-
[Draft] The default output format for status commands is now structured JSON instead of human-readable text. Scripts that parse the previous line-oriented output may fail or consume incorrect values after upgrading. Migration: request the documented machine-readable fields explicitly, update parsers to read the JSON schema, and reserve the text format for interactive use.
-
[Draft] Commands that operate on a workspace now require an explicit workspace context when run outside the repository root. Automation launched from a different working directory may fail instead of silently reading or writing state for the wrong workspace. Migration: run the command from the intended repository root or pass its
--workspaceoption explicitly, and update wrappers that previously relied on the current directory being inferred. -
[Draft] The command-line configuration flag
--confignow accepts only a file path, not an inline JSON object. Scripts that pass configuration directly on the command line will fail validation after upgrading instead of being parsed as before. Migration: write inline configuration to a file and pass that file's path to--config, or use the equivalent environment-based configuration mechanism. -
[Draft] The default configuration directory is now resolved relative to the workspace root. Deployments that relied on the process working directory may load a different configuration after upgrading, which can change dispatch and storage behavior. Migration: move workspace configuration into the repository's
.synlynk/directory, or pass an explicit configuration path wherever the command is run from outside the workspace. -
[Draft] Resource lookup commands now exit non-zero when no match is found. Automation that treats an empty result as a successful no-op will begin failing fast, making missing resources visible instead of silently masking typos or stale identifiers. Migration: handle the documented not-found exit code explicitly when an empty result is expected, and reserve other non-zero codes for actual command failures.
-
[Draft] List-command responses now return an object with
itemsandnext_cursorinstead of a bare array. Clients that iterate over the response directly or deserialize it as an array will fail after upgrading, while the wrapper leaves room for pagination and future metadata. Migration: read records fromitems, treat a missing or nullnext_cursoras the end of the result set, and follow the cursor when fetching subsequent pages. -
[Draft] JSON output for
synlynk jobs --jsonnow wraps records under ajobskey. Consumers that read the previous top-level array will no longer receive a compatible response, making the output extensible without changing its meaning. Migration: read thejobsfield and handle an empty list when no jobs are available. -
[Draft] Event payloads now require an explicit
event_version. Consumers that omit the field will be rejected instead of receiving a best-effort payload, making incompatible contract changes visible at the boundary. Migration: update producers to send the supported version and update consumers to validate it before processing events. -
[Draft] Dispatch task definitions now require an explicit
task_type. Definitions that omit the field will be rejected instead of being inferred from task text, which makes routing failures visible before a job starts. Migration: add the appropriatetask_typeto each existing definition (for example,implement,test, orreview) before upgrading. -
[Draft] Configuration files now require an explicit schema version. Unversioned configuration files will no longer be loaded implicitly, which prevents older layouts from being interpreted as current settings. Migration: add the supported
schema_versionvalue to existing files and runsynlynk migratebefore upgrading; invalid or unsupported versions should be corrected before dispatch can resume. -
[Draft] The default retry policy now fails closed for unknown error types. Jobs that encounter an error not covered by the configured retry policy will stop instead of being retried automatically, preventing non-idempotent work from running more than once. Migration: review custom retry policies, add explicit handling for errors that are safe to retry, and re-run stopped jobs only after confirming that their side effects are safe to repeat.
-
Dispatch jobs now distinguish completed work from true zombie termination (#1498). Previously, any exited worker that still had a disposable worktree could be classified as
killed_zombie(exit-9) before the reconciler read the{log}.exitmarker or inspected real output — including clean design/review jobs. That also deleted worktree-local logs. Migration: treatkilled_zombieas a true orphan only (dead PID, no exit marker, no completion receipt / meaningful work). For cleanup and retry, prefer the job's terminalstatusandexit_code(done/failed). Worker logs now live under the daemon's central.synlynk/logs/directory and are preserved when a disposable worktree is reaped.
Added
-
Cadence-breaker resilience engine: markdown append conflict auto-rebase, active-job circuit breaking at 500k zero-file tokens or $5, startup harness failover, and dead-PID daemon worktree cleanup.
-
Charter Content & Structure Schema
- Charters now require YAML frontmatter (
schema_version,role,description,durability,tools,credentials) plus three markdown sections (## Instructions,## Authority & Escalation,## Workflow Ownership), enforced via a newsynlynk/charter_schema.pyvalidator wired intopropose_charter_revision. - Retired the dead
.synlynk/agents/<id>.yamlprojection file andregenerate_agent_projection()— its only field (capability_grants) was write-only, never read. - Added
synlynk agent sync-routing <id_or_alias>to regenerate a charter'sdispatch_routingfrontmatter block from.synlynk/policy.json's task-allocation table. - Migrated all 7 provisioned charters (dev, qa, architect, pm, tpm, designer, marketing) to schema revision 3;
pm's migration restores the competitive-intelligence-sweep / capability-gap-doc content that had been lost in an earlier revision.
- Charters now require YAML frontmatter (
Agent vs Harness Terminology — Phase 0 (design 2026-08-09, plan 2026-08-09)
docs/glossary-agent-vs-harness.md— canonical definition distinguishing Agent (persistent role identity + charter: pm/architect/tpm/dev/designer/qa/marketing/synlynk-bot) from Harness (swappable execution backend: Claude/Agy/Grok/Codex/local).- Auto-generated
## Capability-Based Task Allocationtable (synced into CLAUDE.md/GEMINI.md/AGENTS.md/GROK.md viasynlynk doctor --fix) now reads| Role | Harness | Tasks |instead of the conflated| Role | Agent | Tasks |, with a glossary-link note. - Hand-maintained "Terminology: Agent vs Harness" section added to this repo's own
CLAUDE.md. .synlynk/roles.yaml,README.md,SYNLYNK_GUIDE.mdwording fixed to stop conflating Agent and Harness.- Not yet a shippable milestone: first phase of a 5-phase roadmap (
docs/superpowers/specs/2026-08-09-synlynk-agent-roles-charters-design.md§10). Phase 1 (agent manifests/charter storage) has since shipped — see[0.14.0]below — but Phases 2-4 (memory, capability registry, portability) remain unbuilt. Held out of 0.13.1 and 0.14.0; will ship as its own named release once the full terminology rollout is complete.
Quota-Aware Dispatch Reservation (design 2026-08-08, plan 2026-08-08)
agent_reservationsledger tracks estimated-token reservations per harness from the moment a job is queued/dispatched until it settles, closing the gap where--force-agentand daemon-queued dispatches could bypass quota checks entirely.dispatch_agent()now consults quota unconditionally (including--force-agentcalls) and defers (queued,blocked_reason=quota_exhausted) instead of raising when a harness has no headroom; deferred jobs resume automatically once the harness's quota window resets — no manual re-dispatch needed._dispatch_ready_jobs()no longer falls through to an exhausted harness when a job is blocked; it stays queued for the next poll.synlynk schedule --executeopens real reservations for the whole batch at commit time via_enqueue_plan()._force_exhaust_quota()wires sentinel's existingQUOTA_EXHAUSTEDdetection into the reservation ledger without ever touching already-running jobs.synlynk/tpm_hooks.py— narrow TPM hook surface (tpm_observe_reservations,tpm_reorder_queue,tpm_reallocate) plus a read-onlysynlynk quota --tpm-viewCLI command to inspect open reservations across harnesses.- Not yet a shippable milestone: no active agents currently exercise the reservation ledger or TPM hooks in production dispatch flow. Held out of 0.13.1 and 0.14.0; will ship once agents actually consume it.
Added
- feat: harness-session gh shim shared with synlynk exec (#1472) - feat(book): make EPUB output Apple Books-ready (#1463) - feat: synlynk exec PATH shim refuses host gh without a token (#1464) - feat: synlynk gh --role runs gh as a role GitHub App (#1453) - feat(harness): dynamic home harness orchestrator parity and dual-mode directives (#1440) (#1440) - feat: research OS-level sandboxing and credential isolation (#1393) (#1405) - feat(onboarding): implement zero-risk dirty worktree guard and instant first-win demo (#1352) (#1372) - feat(swarm): implement ephemeral cloud runner drivers (Fly.io, K8s, local) (#1341) (#1366) - feat(costs): implement subscription cost amortization, extra usage, and true-up reconciler (#787) (#1338) - feat(doctor): add TC-9 in-sandbox gh-write capability probe (#1213) (#1316) - feat(doctor): warn on todo.md hand-edit drift after state.db regeneration (#1220) (#1314) - feat(backlog): GOVERNS backlog automation for discovered work (#1203) (#1313) - feat(dispatch): wire charter content into dispatch and execution context (#1201) (#1312) - feat(db): implement Phase 4 database schema dual-read / dual-write (#1307) (#1311) - feat(fleet): grant Codex full harness parity across review and gh-write tasks (#1274) (#1275) - feat: direct Codex GitHub-write network access via config override (#1268) (#1271) - feat: add doctor check for elevated PR review cycles (#1200) (#1245) - feat: wire charter authority into dispatch/exec context (#1201) (#1233) - feat: add Herdr workspace protocol SOP (#1229)Fixed
- fix(reconciler): harden worker exit detection, log preservation, and event-driven launch DAG (Sprint 4) (#1500, #1501, #1502, #1511, #1527) (#1548) - fix(dispatch): harden worktree deletion safety, auto-PR stacking, and Codex local-write review permissions (Sprint 3) (#1547) - fix(daemon): harden control-plane lock recovery, dual-ledger sync, and key resolution (Sprint 2) (#1546) - fix(worktree): guard empty branch in _gh_pr_for_branch and recognize squash-merged branches (#1536) (#1540) - fix: Task Group 2: capability envelope seeding + concurre (job-ecba9b0b) (#1518) - fix: Task Group 4: docs (job-424d106a) (#1519) - fix(state): harden sandbox DB fallback and reconciliation (#1526) - fix(daemon): recover stale lifecycle locks (#1523) (#1524) - fix(selftest): isolate live probe provisioning (#1517) - fix(ci): align test matrix with supported Python versions (#1505) - fix(dispatch): diagnose and prevent zombie worker termination (#1498) (#1504) - fix: enforce Sentinel lifecycle policy (#1488) (#1491) - fix(selftest): probe cold source ledger before live dispatch (#1490) - fix(selftest): provision probe metadata in live scratch DB (#1485) - fix(review): allow distinct QA App identities to submit approving PR reviews (#1475) (#1476) - fix: review fallback is same-identity comment-checklist only (#1465) - fix: isolate parent auto-pr github auth (#1467) - fix: request actions write for merge-authority apps (#1458) - fix: skip parent auto-PR when no role App token (#1454) - fix: parent auto-PR uses the job role App token (#1452) - fix: resolve PR number from HEAD when pr check runs on a job branch (#1450) - fix: pr check without writing shared todo; drop guessed pytest -k (#1449) - fix: skip injected ## Permissions when auto-finalizing PR titles (#1447) - fix: gh-write verifier leftovers from LIVE-1429 (#1444) - fix: do not mark daemon jobs permission_denied after corroborated success (#1441) - fix: ## Permissions (job-72bf6d52) (#1434) - fix: ## Permissions (job-7c8c84f5) (#1408) - fix: ## Permissions (job-4010ba49) (#1407) - fix: Fix gh:#352 — stall-kill signals a raw stored PID wi (job-93f3f401) (#1419) - fix: ## Permissions (job-d6b97dea) (#1404) - fix: require shared-secret auth on daemon and Vizor HTTP (#1418) - fix: Fix gh:#136 — the daemon_jobs reconciliation path ne (job-f1617bfc) (#1420) - fix: daemon orphan reap on start + exclusive start lock (#349) (#1417) - fix: reconcile terminal jobs across sqlite and jobs json (#1388) - fix: verify gh writes before timeout finalization (#1387) - fix: retry and capture gh review verification evidence (#1380) (#1386) - fix: verify gh writes before killed zombie status (#1385) - fix: verify PR-open GitHub writes (#1384) - fix: restore Codex review network access (#1375) - fix: Implement Autonomous Remediation Loop (synlynk heal) (job-89bd001e) (#1373) - fix: ## Permissions (job-e2061c9a) (#1362) - fix: Implement Living Charter Evolution & Capability-Gate (job-4bf9c7e6) (#1360) - fix: Implement Cross-Harness Inter-Agent Event Relay per (job-38bb3618) (#1358) - fix: ## Permissions (job-8575a177) (#1356) - fix: Implement Cadence-Breaker Resilience Engine per docs (job-25365d40) (#1355) - fix: Implement Phase 1 and Phase 2 of Issue #1343 per doc (job-d6812ef1) (#1345) - fix: ## Permissions (job-9c597160) (#1336) - fix: Implement issue #1327: Deduplicate boolean CLI flags (job-a24af5b3) (#1335) - fix: Implement issue #937: Review-dispatch permissions ha (job-455385e6) (#1331) - fix(team): prevent dropped OAuth codes in manifest callback loopback server (#906) (#1332) - fix: ## Permissions (job-e73d175d) (#1330) - fix(cli): detect and warn on stale pipx-installed synlynk binary vs repo VERSION (#1188) (#1325) - fix(blog): fix malformed YAML frontmatter in post 103 (#941) (#1322) - fix(roles): invoke _repair_sops_only during synlynk roles --fix (#1231) (#1321) - fix(dispatch): tighten _task_requires_gh_write heuristic to eliminate false positives (#1246) (#1320) - fix(tests): decouple README sync validator unit test from live repo root (#1270) (#1319) - fix: grant qa App administration:write for merge roles (gh:#1295) (#1303) - fix(decide): write decision records to tracked project-docs in worktree (#1226, #1194) (#1315) - fix(db): bump _DB_MIGRATION_VERSION to 4 to guarantee migration on pre-existing DBs - fix: replace hardcoded codex approval_policy=untrusted with -s read-only (#1302) - fix(harness): align Claude baseline roles with PM/deploy SOP and clean up permission flag handling (#1284) (#1288) - fix(harness): eliminate Agy headless 5m timeout, enable read-only plan mode, and capture prompt-cache tokens (#1283) (#1286) - fix: daemon re-exec fork-safety + worktree-aware token cache path (#1263, #1264) (#1282) - fix(dispatch): eliminate Grok headless cancellation by adopting --always-approve (#1277) (#1279) - fix: Resolve the remaining correction for ticket 1242 on (job-6e5d67d4) (#1247) - fix: Small follow-up to synlynk tracking item 1202 termin (job-aa57bd84) (#1254) - fix: Implement Task 2 of docs/superpowers/plans/2026-08-2 (job-f4c16542) (#1260) - fix: Fix gh:#1228 — synlynk daemon state paths are CWD-re (job-24507a4d) (#1232) - fix: keep daemon alive across bad job ticks (#1258) - fix: #1250 dispatch job summaries silently report 'files: 0 touched' (#1251) - fix: Fix #1140 (reopened): synlynk daemon start still doe (job-352c9929) (#1249) - fix: checkpoint() todo.md handling bypasses stories table + hardcodes migration-unaware path (#1218) (#1224) - fix: Fix issue #1211 on nikhilsoman/synlynk: the macOS la (job-64daff63) (#1212) - fix: Fix issue #1209 on nikhilsoman/synlynk: 'synlynk dis (job-b6b67e41) (#1210) - fix: repair blog frontmatter YAML (#1208) - fix: trigger site deploys for release content (#1207) - fix: skip harness fence rewrite when content is unchanged (#1204) - fix: #1197 restore org_domain remap on already-migrated connections (#1205) - fix: Fix #1191: add a backfill/registration path for the (job-5cede02f) (#1192)Changed
- docs: checkpoint devlog, memory, and cost log for Sprints 1-4 (#1543) (#1549) - perf(ci): enable pytest-xdist parallel test execution and unstable triggers (#1492) (#1544) - docs: layered release protocol, autonomous operations & time-to-wow arch spec (#1542) - docs: session checkpoint — sentinel triage, worktree fix, and handoff tickets (#1541) - docs: mid-session checkpoint — daemon recovery, dual-ledger sync, and BS-6 landing (#1534) - docs: add BS-6 product/logical/infra visualization spec (#1533) - docs: investigate dispatch token inflation in #1531 (#1532) - perf(cli): profile and defer eager startup imports (#1513) - docs: evaluate pytest-xdist safety for test suite (#1496) (#1512) - perf(selftest): isolate probe metadata from unit-test runs (#1506) - test: isolate archived pytest modules - docs: harness sessions must prepend synlynk gh shim (#1436) (#1471) - docs: qa actions:write re-approval runbook (#1436) (#1466) - docs: synlynk gh --role is the default for session GitHub writes (#1457) - docs: charter patch aligning architect role with qa-only merge authority (#1436) (#1456) - docs: add #1436 bot-authored live cell (#1455) - docs: #1436 identity routing assessment spec (#1451) - docs: blog post for PR #1415 (job status end-to-end regression test) (#1431) - chore: archive unmerged blog-index backfill diff before worktree cleanup (#1364) - docs: update blog post — PR #1437 merged (#1439) - chore: regenerate PDF/EPUB with synlynk glyph cover (#1437) - docs: blog post for PR #1434 (book glyph cover) (#1438) - chore: add EPUB build as default book output alongside PDF (#1430) - docs: research SCIP indexers, Tree-sitter, and Glean code intelligence (closes #1396) (#1406) - test: add end-to-end job status truth regression (#1415) - chore: gitignore node_modules and stray state.db (#1410) - docs: distinguished engineer review + PM triage (#1413) - docs: blog post for PR #1409 (book brand restyle) (#1412) - style(book): align v0.5 draft with synlynk visual system (#1409) - docs: record decision-panel outcome for Model/ModelFamily as first-class citizens (#1378) - docs: devlog entry for PR #1374 merge verification + #1274 fix chain (#1376) - docs: integrate Strategic Review content into the book manuscript (#1374) - docs(specs): add design specs and plans for zero-risk onboarding and autonomous heal loop - docs(plans): add implementation plan for ephemeral swarm cloud runners (#1341) - docs: complete archive of PR 1304 (#1352) - docs(plans): add implementation plans for PM backlog triage (#1340) and living charter adaptive routing (#1342) - docs(plans): add implementation plan for cross-harness inter-agent event relay - docs(plans): add implementation plans for cadence-breaker resilience and marketing engine - docs(specs): add full architecture specs for self-healing, marketing engine, relay bus, swarm runners, and living charters - chore: archive superseded Codex implementation of #1203 (PR #1304, closed) (#1324) - docs(memory): link issue #1343 for First-Class Model Registry - docs(memory): record strategic initiative tickets #1339-#1342 - docs(spec/plan): add first-class model registry and complexity dispatch spec - docs(spec/plan): add subscription cost amortization and true-up design for #787 - docs(memory): record research ticket #1326 for multi-agent swarm engine - Hardening: Prohibit direct todo.md hand-edits across harness instruction templates (#1317) (#1318) - docs: record Phase 4 implementation and merge in agy devlog - docs(blog): record PR #1310 merged on 2026-08-31 - Fleet Parity: Agy Stitch MCP Integration, Diagnostics, and Prompt Guidance (#573) (#1310) - docs(blog): mark post 142 (PR #1309) as merged - Fleet Parity: Instruction file preflight presence check and closed-loop receipt verification (#347) (#1309) - docs(blog): record PR #1308 merged on 2026-08-30 - Fleet Parity: Enforce --cwd for Grok and -C for Codex with working-directory prompt header (#342) (#1308) - docs(todo): record #1307 / story-043eb9ee for Phase 4 DB migration - docs(blog): record PR #1306 merged on 2026-08-30 - Standardize Harness vs Workspace Agent separation across CLI flags, configs, and docs (#1255) (#1306) - docs: spec, plan, blog post, and devlog close-out for daemon re-exec fix (#1263, #1264) (#1301) - docs: GOVERNS backlog automation design + plan (#1203) (#1281) - Marketing goal ownership: charter edit + role-based TPM sweep routing (#1299) - docs: design spec for marketing charter goal ownership (#1294) - docs(book): Part II Onboarding chapter, v0.4-DRAFT (#1292) - docs: author blog posts 137 & 138, sync memory, todo, and devlogs (#1289) - docs: author fleet harness parity reference manual (#1285) - docs: blog post and project-docs sync for PR #1279 (#1277) (#1280) - docs: blog post and project-docs sync for PR #1275 (#1274) (#1276) - docs: sync README with v0.18.0 (#1242) (#1269) - docs: blog post and project-docs sync for PR #1271 (#1268) (#1273) - docs: sync todo.md for 7-PR review backlog closure (#1267) - docs: blog post for #1199 charter corpus grounding (PR #1260) (#1266) - docs: sync todo.md for PR #1232 resolution, file #1264 for token-cache gap (#1265) - docs: sync todo.md for #1228 resolution (#1261) - docs: standardize Harness vs Agent terminology in synlynk/*.py (#1202) (#1256) - docs: sync todo.md — #1140/#1250 landed, review queue cleared (#1257) - docs(blog): PR #1239 post — The Book Gets Co-Authors (#1241) - docs(book): Part 0 + Part I multi-author chapters, v0.3-DRAFT (#1239) - chore: repair harness SOP fences to include Herdr Workspace Protocol (#1230) - docs: check in The Supervised Machine (v0.2 DRAFT) manuscript (#1227) - docs: archive superseded todo/devlog/decision authority spec (#1222) - docs: full RCA for LIVE-11 (checkpoint() todo.md migration-unaware path) (#1221) - docs: record editorial-review decision for The Supervised Machine 2nd Ed (#1225) - docs: ticket-driven approval auto-resume design spec + implementation plan (#1215) - docs: add session topic discipline & cross-harness context transfer design spec (#1214) - docs: recover 2 decision records lost to gitignored write path (#1195) - docs: resync todo.md with current project state (#1216) - docs: retroactive RCAs for LIVE-9 (#1184) and LIVE-10 (#1185) (#1206) - Charter content & structure schema (#1196) - docs: charter authority design — surfacing mechanism, harness-agnosticism, role-portability (#1193)Release pitch: a backlog of already-shipped, undocumented work — QA merge-gate authority, the gh-write broker, harness capability registry v2, and a week of dispatch/gh-write reliability fixes — finally gets a version number, and today's own session shows why that matters: a live datetime-comparison crash (#1184) and a per-connection DB backup storm (#1087) both got root-caused and fixed in the same sitting this release closes out.
Added
QA delegated merge-gate authority + completion tracker + merge-restricted classes (design 2026-08-20/22, gh#1079/#1099/#1100/#1101, PRs #1082-#1104)
docs/superpowers/specs/2026-08-20-qa-merge-gate-authority-design.mdand its implementation plan give QA delegated authority to merge PRs that pass verification, instead of every merge requiring a human or PM-role action.- Completion tracker (PR #1100) adds a Vizor panel surfacing verified-but-unmerged PRs.
- Merge-restricted classes (PR #1101) carve out PR categories (e.g. release branches, policy.json changes) that stay outside QA's delegated authority regardless of verification status.
GitHub-write broker design (resolves #865 brainstorm, PR #1075)
- Design spec for a centralized gh-write broker consolidating GitHub App token resolution and write-permission checks behind one interface, replacing scattered per-call-site identity resolution.
Harness capability registry v2 — Plan B (gh#786, PRs #1053-#1066)
harness_models/harness_modes/capability_calibration_*tables replace the old flat capability ledger with per-model, per-mode calibration data.- Stage 0 explore bonus seeds calibration for thin-data models; single-model sweep entry point and diff-and-queue-new-models helper keep the registry current as harnesses add models.
gh-write identity hardening — Phase 1 closeout (gh#423/#426, PR #1110) and Agent-roles Phase 2 — memory-gated capability routing (PR #1030)
- Round out the identity-hardening and capability-routing work referenced but not yet changelogged from earlier in August.
Dispatch and gh-write reliability hardening (2026-08-24 to 2026-08-27, PRs #1140/#1164/#1166/#1172/#1174/#1175/#1177/#1180/#1182/#1183)
- Daemon-owned GitHub App token cache unblocks headless dispatch (#1140, PR #1174); worktree gh-write dispatch now falls back to the main repo's
github_appswhen the worktree has none (PR #1164). - PR-review task type is now inferred from task text (#1166, PRs #1172/#1175); a missing
reviewtask_allocationpolicy entry is added; grok's review-type gh-write authorization is correctly downgraded (PR #1177). - Codex sandbox network access is now gated per #340 (PR #1180).
- gh-write targets are resolved from task text for #860 (PR #1183); a
jobs.pybug in_maybe_open_worktree_pris fixed (PR #1182). - Harness capability baseline + recurring reassessment protocol documented (PR #1178).
PM competitive-intelligence sweep (PR #1159)
- Weekly cron job maintaining a living comparison doc against competitor tooling, feeding a decide-round pipeline for roadmap input.
Fixed
[LIVE issue] jobs --all crash on naive/aware datetime comparison (gh#1184, PR #1187)
_parse_iso8601()insynlynk/gh_verify.pynow normalizes a trailingZand coerces naive timestamps to UTC-aware before comparison, instead of crashing withTypeError: can't compare offset-naive and offset-aware datetimeswhenever a GitHub-sourced timestamp reachedgh_write_verified()._apply_gh_write_verification()insynlynk/jobs.pynormalizessincethrough the same parser before use.
[LIVE-6, gh#1140] branch-protection sync re-enabling enforce_admins, closing #1185 (PR #1186)
cmd_policy_sync_branch_protection()no longer hardcodesenforce_admins=True; a prior sync had silently re-locked the repo's own admin-merge bypass.
[LIVE issue] _migrate_db() backup storm on every connection (gh#1087, PR #1189)
_migrate_db()now returns immediately oncePRAGMA user_versionis current, instead of running the harness-rename migration and full schema executescript unconditionally on every connection. Root-caused as the likely source of intermittentdatabase is lockedfailures seen during full-suite test runs (e.g.test_cmd_agent_add_onboards_agent).
Process notes
- 8 stale
[APPROVAL]GitHub issues closed (gh#1142-#1149): artifacts of the[0.17.0]Task 5 live dogfood verification's temporarytask_dispatch_demopolicy rule, which was fully reverted before merge and never landed onmain. These tickets could never resolve through the normal auto-resume flow; closed asnot plannedwith provenance comments during this release's backlog sweep. - Version-drift note: the
VERSIONfile had drifted to0.16.0despitev0.17.0already being tagged and released — see #1188 for root cause and proposed durable fix (dispatch-time drift warning, defensive schema-version gate). This release's version bump corrects the immediate drift; #1188 remains open for the systemic fix.
Release pitch: an approved [APPROVAL] ticket now actually unblocks the story it was raised for — the last gap between v0.16.0's authority layer and a tpm sweep loop that runs unattended for real, closed and live-verified against this repo's own GitHub tracker.
Added
Ticket-driven approval auto-resume (design/plan 2026-08-24, PRs #1137-#1139, #1141)
- Closes the known gap flagged at the end of
[0.16.0]: resolving an[APPROVAL]ticket now actually unblocks the parked story on the nextsynlynk tpm sweeppass, instead of the story re-parking forever. approval_ticketstable (PR #1137) plus_find_ticket()/_insert_ticket()/_mark_ticket_consumed()helpers insynlynk/db.py(PR #1138) giverun_sweep_pass()(PR #1139) three-way state awareness per story/action: no ticket yet → file one; open ticket → keep parking; resolved ticket → consume it and let dispatch proceed.synlynk/events.py's_scan_approval_tickets()(PR #1141) now writesapproval_tickets.status='resolved'at the same point it emitsapproval_resolved, so the resolution is durable state the next sweep pass can actually query — not just an event log entry nothing consumed.- Live dogfood verification (Task 5, Claude-direct per plan, 2026-08-24): ran the full ticket lifecycle against this repo's real GitHub issue tracker using a temporary, fully-reverted
task_dispatch_demopolicy rule (reverted before merge; never landed onmain). Demo storystory-becf09a5: sweep 1 parked it and filed ticket id 8 → issue #1149; sweep 2 confirmed no duplicate ticket/issue;gh issue comment 1149 --body "approve"+scan_local_events()producedapproval_resolvedevent id 371 referencing issue #1149; sweep 3 dispatched instead of re-parking (jobjob-e8277299, exit 0) and marked the ticketconsumed(consumed_atset). Every claim was verified via direct DB query /gh issue list/synlynk events tail, not sweep's own printed summary. - Process note: Tasks 1-4's implementer stage was dispatched to Codex per the project's PM/review-only split as usual. Task 4 hit a session-level blocker — the Claude Code auto-mode classifier repeatedly denied
synlynk dispatchcalls even with valid role-scoped GitHub App credentials — so Task 4 was implemented directly by Claude as a documented, user-approved workaround. Filed as LIVE-6, #1140 (Sev2) since it degrades the autonomy-design goal; root cause not yet investigated.
Known gaps (carried forward)
- LIVE-6, #1140 — Claude Code auto-mode classifier blocks
synlynk dispatchcalls even with valid role-scoped GitHub App credentials, forcing a manual-implementation fallback. Root cause not yet investigated.
Release pitch: the authority layer v0.15.0 built now actually gates something unattended — synlynk tpm sweep walks ready stories through dispatch end-to-end, pauses on a policy-flagged action with a GitHub approval ticket instead of blocking the whole batch, and a live dogfood run proved both the happy path and the pause+ticket path work — surfacing two real gaps in the process, filed rather than papered over.
Added
GOVERNS awaiting_approval event (Task 10, PR #1125)
- New GOVERNS event type extending the
job_terminal/review_submittedevent-contract pattern (PR #922):emit_awaiting_approval(story_id, action, reason)insynlynk/events.py, recording whichpolicy.jsonapproval_required_forrule matched.
Approval-gate ticket flow (Task 11, PR #1126)
synlynk/approval_gate.py—raise_approval_ticket()files a[APPROVAL] <action> — <story_id>GitHub issue with story context, the matched policy rule, and instructions to replyapproveor act directly on GitHub.synlynk/events.py's_scan_approval_tickets()polls open[APPROVAL]issues and emitsapproval_resolvedfor any that are closed or have anapprove-prefixed comment, wired as the last step ofscan_local_events().
synlynk tpm sweep (Task 12, PR #1127)
- One pass over
readiness='ready'stories: dispatch → verify → PR → review → merge per story, gating every step oncheck_authority(). Arequires_approvalresult parks that story (raises a ticket, emitsawaiting_approval) without blocking the rest of the batch. Per-pass summary surfaced viasynlynk status.
Live dogfood verification (Task 13, Claude-direct per plan)
- Ran
synlynk tpm sweepunattended against this repo's real backlog. To avoid dispatching all 8 pre-existing ready stories for real, the 8 were temporarily parked (synlynk story draft) and restored afterward; only two purpose-built demo stories were swept. - Pass 1 (no approval rule active) proved the normal path:
story-028d26d9dispatched, ran to completion, PR opened. - Pass 2 (a temporary, documented, fully-reverted test-only
policy.jsonrule —task_dispatch:has no default rule that can triprequires_approval, since_matches_approval_rule()explicitly skipssecurity_sensitive_paths:for dispatch actions) proved the pause path:story-7aa0aaecparked, a real[APPROVAL]issue was filed and assigned,approvewas commented, and_scan_approval_tickets()correctly emittedapproval_resolved(event id 272) — independently confirmed viasynlynk events tail --type approval_resolvedandgh issue view --json state,comments. - Every claim was cross-checked directly (
synlynk jobs --all, direct DB queries,gh issue list --search,gh api .../branches/main/protection) rather than trusted from the sweep's own printed summary, per the plan's explicit instruction.
Fixed
/ Known gaps (filed, not patched in this release — Claude is PM/review only; fixes are implementation work for a future dispatch) - **`scan_local_events()` crashes before reaching `_scan_approval_tickets()`** (`sqlite3.OperationalError: table subscriptions has no column named harness_name`), and its only production call site (`workspace_agent.py`'s `cmd_workspace_agent_run`) has no wired CLI subcommand — meaning the documented approval-resolution detection path does not actually run unattended today. Filed as [#1132](https://github.com/nikhilsoman/synlynk/issues/1132). - **`synlynk story done` does not clear `readiness`**, and `_ready_stories()`'s in-flight guard only excludes `queued`/`running` jobs, not `done` ones — so a story whose dispatch already completed gets re-swept and re-parked on the very next pass, observed live with `story-028d26d9`. Filed as [#1133](https://github.com/nikhilsoman/synlynk/issues/1133). - **Resolving an approval ticket does not auto-unblock a re-sweep**: `check_authority()` is purely policy-rule-based with no awareness of ticket-resolution state, so `approval_resolved` firing does not itself let the parked story advance on the next pass. This matches the plan's own scoping (ticket-driven auto-resume was explicitly out of scope for this plan) — a known limitation, not a regression, and the natural next increment once #1132/#1133 are fixed.Release pitch: synlynk's own repo gets a real authority layer — a two-tier policy.json (workspace defaults + per-repo overrides) that turns previously-hardcoded prose tables (who can merge, who can cut a release, who can edit the roadmap, which harness handles which task type) into data, gated by a fail-closed check_authority() resolver, with branch protection now live-verified on main.
Added
Workspace Policy Layer (design 2026-08-23, plan docs/superpowers/plans/2026-08-23-workspace-policy-and-autonomous-loop.md, PR #1122)
synlynk/policy.py— two-tier policy schema: workspace defaults (~/.synlynk/workspaces/<name>/policy.json, falling back toDEFAULT_WORKSPACE_POLICYwhen absent) merged with a repo's sparse.synlynk/policy.jsonoverrides, whole-object-replace-per-top-level-key (not a deep merge).check_authority(action, role, repo_path)→AuthorityResult(allowed, requires_approval, reason), coveringroadmap_edit,goal_create,merge,release_cut, andtask_dispatch:<type>actions, plus anapproval_required_forrule matcher (named releases, roadmap-authority changes, security-sensitive paths, irreversible merges).- Wired fail-closed into four call sites:
dispatch_agent()'s task-allocation resolution,cmd_release,cmd_roadmap_add,cmd_goal_create— each raisesRuntimeErroronallowed=Falserather than proceeding. synlynk policy check-merge,synlynk policy sync-branch-protection,synlynk policy show— new CLI commands;sync-branch-protectioncalls GitHub's branch protection API idempotently, deriving required status checks from.github/workflows/.- This repo's own
.synlynk/policy.jsonmigrates the existing CLAUDE.md prose tables (Capability-Based Task Allocation, PR Review Discipline, Named Release authority) into data — CLAUDE.md now points tosynlynk policy showas the source of truth instead of hand-maintained tables. - Full
check_authority()unit coverage: allow/deny/requires_approval across both tiers, override-merge rule, missing-repo-override inheritance, unknown task_type denial (tests/test_policy.py, 11 tests). - Live-verified: branch protection synced and independently confirmed via
gh api repos/nikhilsoman/synlynk/branches/main/protection—required_status_checks=["test (3.8)", "test (3.10)", "test (3.12)", "qa-gate"],required_reviews=1,enforce_admins=true.
Fixed
- Default `role="dev"` on `cmd_release`/`cmd_roadmap_add`/`cmd_goal_create` didn't match the default policy's `pm`-only authority for these actions, causing unspecified-role calls (including coldstart's own roadmap-row write) to fail closed. Defaulted to `role="pm"`, matching the actions' actual authority scope. - Taxonomy regression: two new `policy` subcommands were missing `COMMAND_TAXONOMY` entries, failing `test_taxonomy_matches_real_cli_surface`.Release pitch: the execution floor gets a truth guarantee — every GitHub-write dispatch now has its claimed outcome independently verified against live GitHub state instead of trusted at face value — and workspace agents get a real identity: a storage-backed charter, a synlynk agent init/list/show/edit/disable onboarding surface, and dispatch integration that resolves role and harness from that identity automatically.
Added
GOVERNS Job-Truth / GH-Write Consolidation (#701, PR #978) — closes #331, #579, #935
synlynk/gh_verify.pygh_write_verified()— an independent delivery-of-effect check that queries live GitHub state via the orchestrator's ownghidentity (not the sandboxed job's), replacing "the job said it succeeded" with "GitHub confirms the write landed."- Wired into
dispatch.py's_check_job_stall(extends timeout on an unverified write, kills the job on a confirmed failure) andjobs.py's_reconcile_daemon_jobs(newsucceeded_gh_write_failedterminal status distinct from a clean success). gh_write_verifiedsurfaced as a column insynlynk jobsoutput.- Regression guard (
tests/test_gh_write_guard.py) asserting every terminal-status-deciding code path for a--requires-gh-writejob consults the check. synlynk doctorTC-7 preflight verifies Agy's localghallow-rules before routing gh-write tasks to it, instead of failing at dispatch runtime.- Codex PR-review tasks now route through the
ghCLI directly instead of the previously-unreliable MCPadd_review_to_pr/add_comment_to_issuetools.
Workspace-Scoped Agent Artifact Storage (design 2026-08-14/15, gh#936, PR #988)
- Mints a real
workspace_id(uuid4, persisted once in.synlynk/config.json) keying a new workspace-level agent artifact store. agent_idregistry (register_agent/resolve_agent_id) mirroring the existingmember_id/member_aliasespattern — loud failure on an unregistered alias, rejects duplicate agent_id/alias.- Canonical
charter.md+ provenance-chainedcharter.revisions.jsonlstorage (read_charter/propose_charter_revision) with stale-parent-revision conflict detection, extended tomemory/andstatements-of-record/entries. regenerate_agent_projection()writes a generated, gitignored.synlynk/agents/<agent_id>.yamlprojection (agent_id/role/overrides only, never charter content) via a stdlib-only flat YAML emitter.
Agent-Roles-Charters Phase 1 — CLI Onboarding + Dispatch Integration (design 2026-08-16, PR #1003)
synlynk agent init/list/show/edit/disable— the CLI onboarding surface for workspace agents (org-chart roles: dev/qa/pm/architect/tpm/designer/marketing/synlynk-bot), built on the storage layer above.dispatch_agent()gainsagent_idsupport: validates the agent is registered/enabled, resolves its role, auto-selects a harness by capability fit when none is forced, and threads the resolved role into GitHub-identity/token resolution (taking precedence overstory_id-derived role when both are present).synlynk dispatch --as-agent <id_or_alias>— makes theharnesspositional argument optional when--as-agenttriggers auto-selection.
Agent → Harness CLI Rename (PR #993)
- Renames
synlynk agent add/configure/run/listtosynlynk harness add/configure/run/list, resolving the naming collision between execution-backend harnesses and the workspace/role-identity agents introduced above. No deprecation shim — pre-1.0 breaking change, decided via a 4/4synlynk decide --panelvote (project-docs/decisions/2026-08-16-synlynk-s-cli-has-a-naming-collision-syn.md). - Frees the
agentCLI verb for the onboarding surface above.dispatch <agent>,open <agent>,probe --agent,quota --agentare untouched — those use "agent" in unrelated senses.
TPM/Session MVP (plan 2026-08-13, PRs #934, #944, #950, #954, #959)
sessionstable +synlynk/session.pyactive-session marker file helpers.devlog_entriesgainssession_id/goal_idcolumns;cmd_devlog_append()auto-inherits the active session when not passed explicitly.session_idthreaded throughdispatch_agent()→daemon_jobs→cost_entries(with inheritance from job to cost row), so every dispatch and its cost are attributable to the session that launched it.synlynk dispatch --session <id>override flag.synlynk session statussurfaces a NUDGE line whendaemon_jobshas rows with nosession_id— the first concrete TPM-facing signal for unattributed work.
Fixed
- Devlog identity re-fork prevented by resolving the devlog path through the `member_id` registry instead of a raw filename match (#956). - Dispatch stall-timeout extended for review-only jobs, which previously could be killed mid-review before posting (#939). - Review-only `synlynk dispatch` jobs no longer get miscounted against implementation-job budgets (#943, closes #937).Housekeeping
- Worktree/job accumulation (#559) audited and closed without new code:
synlynk worktree audit/worktree clean(shipped pre-0.13.1 in PR #676) already covers the core ask;synlynk status's existing staleness hint covers the proactive-warning ask. Re-verified against this repo's own worktree state during the audit.
Release pitch: synlynk gets safer to operate on — init/migrate/upgrade can now roll back on failure, project docs are DB-canonical instead of hand-parsed markdown, the GOVERNS event bus gains job-terminal and review-submitted events plus a synlynk events tail command, and a new doctor check catches invalid GitHub tokens before a dispatch wastes a turn discovering them.
Added
GOVERNS Event-Contract Extension (design 2026-08-12, plan 2026-08-12, #922)
job_terminalevent — emitted synchronously from_reconcile_daemon_jobs()for every daemon job reaching a terminal state, payload{job_id, status, cost_recorded, dispatch_context}.review_submittedevent — emitted fromscan_local_events()for each GitHub PR review not already represented, payload{pr_number, reviewer_login, reviewer_role, verdict}, withreviewer_rolederived from bot-login patterns.synlynk events tail [--type TYPE] [--limit N]— read-only CLI command listing recent events newest-first directly from theeventstable.
Init/Migrate/Upgrade Rollback Mechanism (design 2026-07-22, plan 2026-07-22)
rollback_checkpoint(Leg 1) wrapsinit()andcmd_migrate()in a git-checkpoint + untracked-state backup, auto-restoring on any mid-operation failure.rollback_checkpoint_upgrade(Leg 2) wraps_run_upgrade()in a global install snapshot (pipx reinstall-by-tag / script bin+lib backup), auto-restoring on upgrade failure.synlynk rollback [--last|<op-id>|--clear]— manual rollback CLI, restoring or discarding the most recent (or a specific) checkpoint manifest.--dry-runonsynlynk initandsynlynk upgrade— preview what would be written/changed without touching disk or making network/subprocess calls.- Failure-injection live selftest coverage for both rollback legs, plus dedicated
rollback --last/--clearscenario tests.
State Engine PR1 — DB-canonical roadmap/memory/costs (design 2026-07-20, plan 2026-07-25)
roadmap.md,memory.md, andcosts.mdare now write-through generated fromstate.db(roadmap_arcs/roadmap_phases, memory_entries, cost_entries), with rotation/archive and a warn-and-continue mutation guard for hand-edits.check_budgets()readscost_entriesdirectly instead of regex-parsingcosts.md.synlynk migraterun on this repo itself —project-docs/relocated under.synlynk/,.synlynk_migratedsentinel committed.
synlynk doctor TC-6 — GitHub CLI auth check (#928, closes #577)
- New check across all 4 dispatch harnesses (claude, codex, agy, grok) inspects
gh auth statusoutput for known invalid-token marker strings even when the command exits 0 — the documented false-green failure mode where a dispatch sandbox has a broken GitHub token butghdoesn't report a nonzero exit.
Fixed
- Bumped
linkify-itto 5.0.2 inwebsite/package-lock.json, resolving a high-severity quadratic-complexity DoS (CVE-2026-59887, GHSA-v245-v573-v5vm) in itsmailto:schema validator. Dev-only, transitive viamarkdown-it; fixes GitHub Dependabot alert #6. synlynk jobsnow resolves the repo's real default base branch beforegh pr create, avoiding hardcoded--base mainfailures on repos whose default branch ismasteror another tracked branch.synlynk dispatch agynow warns when no write/run permissions are granted, so headless dispatches do not fail silently when approval-gated tool calls are auto-denied.- Bumped
brace-expansionto 1.1.16 inwebsite/package-lock.json, resolving a high-severity exponential-time DoS (CVE-2026-13149, GHSA-3jxr-9vmj-r5cp) in expansion of consecutive non-expanding{}groups. Dev-only, transitive viaminimatch; fixes GitHub Dependabot alert #7.
Docs
docs/rca/2026-08-13-dispatched-pr-review-cancellation-714.md(#929, closes #714) — RCA concluding Grok'scancelledstopReason on dispatched PR reviews is harness-side, not a synlynk stall/timeout bug; no code change warranted.
Release pitch: synlynk learns to explain itself — every command now has a discoverable taxonomy entry with a maturity-tiered reveal, a live selftest exercises all 59 commands end-to-end, cost accounting gets payment-model awareness and a task-boundary fence around actual spend, and dispatch routing gets capability-aware enough to stop sending GitHub-write work to agents that structurally can't do it.
Added
Command Taxonomy, Maturity-Tiered Reveal, and Trigger Registry (design #303, PRs #304/#305/#309/#310/#311/#312/#316/#319/#320/#321)
COMMAND_TAXONOMYbecomes the single source of truth for all 59 commands —cli.py'sbuild_parser()extracted standalone (#304), taxonomy command surface restored and hardened (#305), defaultfenced_commandsallowlist (#309).- Command reference docs now generate directly from
COMMAND_TAXONOMY(#316) instead of hand-maintained markdown, closing a recurring drift source. - FTUE wizard and the
synlynklaunch picker are now driven by the same taxonomy (#319), so first-run onboarding and the reference docs can never disagree about what a command does or which tier it belongs to. - Tier-scoped trigger phrases wired into
synlynk:start/synlynk:endsession fencing (#320). - Pre-commit hook installed on
synlynk initto gate instructions drift between the taxonomy and generated CLAUDE.md/GEMINI.md/AGENTS.md content (#321).
Task-Boundary Cost Fence (story-615bc8f4, PRs #313/#314/#315/#317)
synlynk exec's actual-cost print now routes through a dedicated cost fence at the task boundary (#313) rather than being computed ad hoc per call site, closing a class of under/over-reporting bugs where a task's real spend diverged from whatcosts.mdrecorded.- Shipped and marked complete in the roadmap (#314); PM session cost for the execution itself logged per the Cost Capture Protocol (#315, #317).
Live Command Selftest (PR #328, follow-ups #335/#337)
synlynk selftest— a taxonomy-driven smoke test that exercises all 59 commands, catching command-surface regressions the unit suite doesn't (drift betweenCOMMAND_TAXONOMYand actual CLI behavior, broken flag wiring, silent crashes on real invocation).- Blog post documenting the design and implementation (#335).
- Follow-up fix: live paid selftest scenarios now rebind
DB_PATHto a scratch workspace instead of touching the real project DB (#337, scenario N6).
Capability Sweep + Industry Taxonomy (PR #367)
synlynk capability sweep— a taxonomy-driven calibration sweep scoring agent capability against NAICS/APQC/SFIA-coded skill axes, seeded fromsynlynk/capability_baseline.jsonand reinforced organically as real PRs land, with a configurable$10cost guardrail (capability_sweep.cost_cap_usd) and independent cross-agent verification scoring.- Legacy free-text
discipline/org_domain/industryvalues are crosswalked to NAICS/APQC/SFIA codes on migration, tagging unmatched valueslegacy_unmappedrather than dropping them.
Payment-Model-Aware Cost/Value Accounting — PMA-1 through PMA-6 (PR #374)
- Cost and value accounting now distinguishes payment model (subscription-seat vs. metered/API) so
costs.mdand budget reporting reflect what was actually spent under each agent's real billing arrangement, instead of a single blended token-rate assumption. - Manual cost entries gained payment-column population (#402); historical entries backfilled with
api_equivalent_usdfor cross-model comparison (#388). - Roadmap and devlog synced for both Capability Sweep (#367) and PMA (#374) landing together (#375).
Story-ID Auto-Provisioning for Dispatch (PR #407)
dispatch_agent()now auto-provisions astory_idwhen a dispatched task has none, closing a gap where ad hoc dispatches (not tied to an existing story) fell outside cost/capability tracking.
can_gh_write Capability Routing (issues #423/#426, PRs #427/#432/#438)
AGENT_CAPABILITY_BASELINESgained acan_gh_writefield so dispatch routing can structurally avoid sending GitHub-write work (gh pr review/merge) to agents that can't complete it headless (Agy, Codex, local) — previously enforced only by SOP convention (#427, #432 codified the convention first; #438 made it structural).- New
--requires-gh-writedispatch flag and enforcement logic indispatch_agent().
Fixed
synlynk watchcrash onCYCLES.index("work")(issue #421, fixed by #301, released here): thev0.12.0tag shippedcmd_watch()still looking up a"work"cycle name that had already been renamed out ofhud.py'sCYCLESlist under the GOVERNS seven-stage vocabulary rollout, raisingValueError: 'work' is not in liston every invocation. The fix (CYCLES.index("execute")) merged tomainvia #301 two days after thev0.12.0tag, but was never shipped in a release until now.synlynk viz --serveexits immediately, nothing binds the port (issue #421, PR #440, merged as #421):_start_server()spawned the HTTP server on adaemon=Truethread and returned immediately with no blocking call, so the process exited (killing the daemon thread with it) right after printing "Serving at...". Not a sandbox/forking artifact — reproduced identically in a real terminal. Fix adds_serve_until_stopped(), which blocks the main thread untilKeyboardInterruptand then cleanly shuts the server down.synlynk migratefalse-positiveMigrationImportErroron idempotent re-runs (#276, #278): natural-key collisions on re-import no longer trip the loud-fail check.- Dispatch auto-PR branch detection re-derives the worktree's actual current branch instead of trusting the pre-recorded name (#280, #283).
synlynk probeclearsHARNESS_VERSION_DRIFTfor the specific agent just re-probed (#281, #284).synlynk agent add <name>retrofits onboarding for a newly available CLI agent already on$PATH(#277, #285), plus lazy daily housekeeping on the firstsynlynk execof a new calendar day.- Token-outlier cost entries now flagged safely instead of silently corrupting averages (#295).
- Stale Cost Visibility / Repo Hygiene SOP text corrected (#290, #296).
- Per-provider model rates with freshness checks across
costs,doctor, andsentinel(#289, #297). - Probe version-token parsing fixed (#294); model version now resolved from agent config files (#287, #292).
agent_quotasnow populated from telemetry, plus a newsynlynk quotaCLI (#291, #293).- Job summary overwrites guarded against clobbering (#387).
- Dispatch worktrees branch from a fresh
origin/maintip instead of a potentially stale local ref (#398, #395). - Headless permission denials correctly classified, avoiding false positives from echoed source text (#399, #404).
- Agy permission dispatch enabled (#417).
- GitHub issue #379 follow-up:
.gfile handling fix (#384). __init__.pymodularisation epic marked shipped, closing stale #380 (#401).
Design specs: docs/superpowers/specs/2026-07-21-command-taxonomy-maturity-reveal-design.md, capability sweep and PMA specs referenced in PRs #367/#374. Roadmap rows synced for Task-Boundary Cost Fence, Command Taxonomy, and Live Command Selftest (#416). State Engine tiered design (single-user/team/enterprise) drafted for a future release (#412) — not shipped in this version.
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_entriesgained explicit provenance columns:cost_source TEXT NOT NULL(actual|estimated_token_rate|estimated_tshirt|estimated_manual|legacy_unknown, no default — everyINSERTmust pass it explicitly) andestimate_basis TEXT. Migration rebuilds the table and backfills historical rows aslegacy_unknown._insert_cost_row()(synlynk/db.py) is now the sole sanctioned writer tocost_entries, replacing four independently-drifting direct-SQL write sites indispatch.py,jobs.py(×2), andsupport_engineer.py. Upserts byjob_idwhen present. Enforced by a call-site audit test that fails the suite if any other file writes tocost_entriesdirectly.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 bysynlynk init) is now the source of truth for per-model rates andbilling_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'sestimated_tokenscolumn → historical average fromcost_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, taggedestimated_manual.- Cost coverage closed across every surface identified in the design spec's audit:
dispatch_agent()'s exec wrapper (no longer gated onin_tokens > 0),jobs.py's reconcile and daemon-reconcile paths,cmd_launch(), andsupport_engineer.py's investigation runs.synlynk release,synlynk probe, andsynlynk doctoraudited 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.mdand 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 survivesupdate_costs()'s 20-character command truncation, restoringcheck_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)
localjoins claude/codex/agy/grok as a dispatchable agent, running as anaiderCLI subprocess against an on-device oMLX OpenAI-compatible endpoint — zero per-token cost.- Capability envelope seeding + concurrency guard so
localstarts 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_cisignals), a hard quota-headroom gate (agent_quotastable 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/readinesscolumns,synlynk story ready/draftgate, 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_capabilityrow 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 dedicatedgit worktreeper dispatched job (worktrees/<job_id>, branchdispatch/<agent>/<job_id>) instead of sharing the invoking shell'scwd— 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_touchedis real (viagit diff --name-only <merge-base> HEAD+git status --short --porcelain), no longer hardcoded to[].cmd_migrate()prints the resolvedDB_PATHand fails loud withMigrationImportErroron 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/storiesrollups in the HUD. __init__.pyre-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 viagh pr createif none exists. - Borrowed-worktree completions attributed via
origin/<branch>state instead of being misread as zero-work. HARNESS_INTERNAL_TIMEOUTjobs now auto-retry (cap 2) instead of landing as a dead failure.- A job that raced its own disk writes and landed
failedwith0 touchedis re-inspected once and reclassifiedfailed_unverifiedrather 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);localgets an explicit $0.0 override regardless of model version. - Capability router now filters on canonical
discipline, not the legacyengg_domaincolumn. - 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
FAILEDwith 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 fromAGENT_CAPABILITY_BASELINESinstead 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 fullnow warns when used on a task that's already self-contained.
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.jsonmap 12 roles (pm, review, implement, test, css, infra, etc.) to capability tiers. Resolved set translates to--allowedTools(Claude),--ask-for-approval(Codex), or a## Permissionscontext 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 withHANDOFF_PENDINGsentinel (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 Noteto the job context file, incrementshandoff_count, updatesprevious_agents(JSON array), launches new dispatch with full context, clearsHANDOFF_PENDING.synlynk doctorTC-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 initandsynlynk synctime: PR Review Discipline · Brainstorm-First Policy · Design → Plan → Build Sequence · Capability-Based Task Allocation · Cost Visibility · Repo Hygiene. daemon_jobsschema 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 vizbrowser 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 matrix —
6 × 4table (dream/plan/work/ship/maintain/engage × Claude/Agy/Codex/Grok) with full/partial/none badges (cap-full,cap-partial,cap-noneCSS 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.dbtables:harness_status,cycle_capability;probecommand extended to seed Tier 1 capacity baselines. synlynk/status.pynew module;HarnessSnapshotdataclass inhud.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__.pyreduced 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_flagsbaseline including--non-interactive(valid for Agy but flagged as invalid by harness validator). Corrected per-agent flag baseline maps. - Fixed
_run_tc2seeding invalid flags into the passed list on first scan, blocking all subsequent Agy dispatches. synlynk logsnow shows exit summary + TC-2 preflight gate result per dispatch.
BS-12 review fixes
--repair-sopsnow merges missing SOP blocks into existing harness fence body instead of replacing the entire fence.- TC-5 result wired into
all_passedincmd_doctor; doctor now exits non-zero when SOPs are missing. - Handoff note included in
handoff_tasksent 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=) inconfigure agentnow usespartitioninstead of crashing withValueError.
BS-22 review fixes
- Removed
is_placeholdershort-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/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 openreplaces oldsynlynk launch <agent>for direct agent open. (BS-19, PR #94)synlynk roles— print current agent role table from.synlynk/config.json;synlynk initandsynlynk doctornow generate per-agent directive role blocks (## Your Rolein CLAUDE.md, GEMINI.md, AGENTS.md). (BS-12a, PR #95)
State + Migration
synlynk migrate— one-shot atomic import ofproject-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_issuecolumn onstories. - DR sync — configurable
dr_sync_pathin.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 launchtemplates 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 viasynlynk 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 indocs/blog/;--dry-runpreviews 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 fromstate.db, served athttp://localhost:8721. Views: Gantt (accordion drill-down, stage bars, pencil notes), User Journeys (split-pane,docs/journeys/*.md), Architect Map (tube map SVG fromvizor-tube.json), Effort & Cost (SVG bar charts), Efficiency (agent report cards + sentinel timeline). Sticky note system:POST /note→viz-notes.json→ injected intogenerate_context()(visual annotation → AI context loop). Live JS polling + browser notifications. Zero new deps. (BS-21, PR #101)
Packaging
- pipx packaging —
pyproject.tomlwith[project.scripts]entry point; VERSION is the single source of truth insynlynk/__init__.py(pyproject.toml reads it via dynamic attr). Install viapipx install git+https://github.com/nikhilsoman/synlynk. _detect_install_type()— detects pipx vs pip vs script install;synlynk upgraderoutes topipx upgrade synlynkwhen 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.
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`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: GrokFixed
- Stale time-sensitive fixture in `test_collect_capability_drop_returns_finding` — hardcoded 2026-06-21 timestamps replaced with `datetime.now(timezone.utc)`-relative valuesAdded
- `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/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 restartAdded
- `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/Fixed
- None in this releaseAdded
- `--docs-dirFixed
- 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).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 shimFixed
- `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 correctlyAdded
- `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 candidatesAdded
- `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 heuristicsFixed
- `synlynk scan` no longer traverses `.git/`, `node_modules/`, or `.synlynk/` directoriesAdded
- 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/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`Added
- SQLite WAL state database (`~/.synlynk/projects/Added
- 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 archivalAdded
- Section marker system: synlynk-managed blocks in instruction files delimited by `` / `` 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/Fixed
- `init` no longer regenerates files that already contain a synlynk section — protects user customisations from accidental overwriteAdded
- `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/Fixed
- `_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 flagsInfrastructure
- 5 new reconcile/enrich tests; 4 new E2E tests (dispatch, jobs, logs, reconcile startup)
- 188 tests total (up from 140)
Added
- 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 --agentsChanged
- `synlynk init` now writes `project-docs/.synlynk_config.json` directly (previously missing from init, requiring manual creation)Fixed
- `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 behaviorRemoved
- Dead functions
log_telemetry(),extract_tokens(), andupdate_costs()— superseded bylog_telemetry_event()and manual cost tracking; removed to prevent confusion
Infrastructure
.gitignoreexpanded to cover.synlynk/,__pycache__/,*.pyc,.DS_Store,test_archive/,test_context_output/,.venv/project-docs/roadmap.mdupdated to reflect v0.2.x reality (was stale with v1.2/v1.3/v1.4 references)- Test added for exit code propagation (47 tests total)
Added
- `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`Changed
- `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`Fixed
- Type hint `str | None` replaced with `Optional[str]` for Python 3.8 compatibility (union syntax requires 3.10+)Infrastructure
- Added pytest test suite (
tests/conftest.py+tests/test_synlynk.py) with 46 tests andproject_dirfixture - Added GitHub Actions CI workflow (runs pytest on Python 3.8, 3.10, 3.12 on push and PRs)
- Added
LICENSE(MIT),CONTRIBUTING.md, PR template, issue templates
Initial public release.