Raw JSON report machine-readable
{
"data": {
"repo": {
"topics": [
"agents",
"ai"
],
"is_fork": false,
"size_kb": 62944,
"has_wiki": true,
"homepage": null,
"languages": {
"Go": 5425574,
"CSS": 35448,
"HTML": 26477,
"Shell": 424028,
"Makefile": 2016,
"Dockerfile": 721,
"JavaScript": 24380
},
"pushed_at": "2026-07-18T19:48:34Z",
"created_at": "2025-12-09T06:44:31Z",
"owner_type": "User",
"updated_at": "2026-07-18T19:48:38Z",
"description": "A minimalist CLI for tracking tasks across AI coding sessions.",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "Go",
"significant_languages": [
"Go"
]
},
"owner": {
"blog": "http://marcus.pictures",
"name": "Marcus Vorwaller",
"type": "User",
"login": "marcus",
"company": "Avalara",
"location": "Seattle, Washington",
"followers": 217,
"avatar_url": "https://avatars.githubusercontent.com/u/3090?v=4",
"created_at": "2008-03-14T14:33:29Z",
"is_verified": null,
"public_repos": 28,
"account_age_days": 6706
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v0.51.2",
"kind": "patch",
"published_at": "2026-07-18T16:00:12Z"
},
{
"tag": "v0.51.1",
"kind": "patch",
"published_at": "2026-07-18T15:02:33Z"
},
{
"tag": "v0.51.0",
"kind": "minor",
"published_at": "2026-06-21T04:06:59Z"
},
{
"tag": "v0.50.1",
"kind": "patch",
"published_at": "2026-06-20T22:09:47Z"
},
{
"tag": "v0.50.0",
"kind": "minor",
"published_at": "2026-06-20T21:48:10Z"
},
{
"tag": "v0.49.0",
"kind": "minor",
"published_at": "2026-06-19T16:13:15Z"
},
{
"tag": "v0.48.0",
"kind": "minor",
"published_at": "2026-06-19T01:04:41Z"
},
{
"tag": "v0.47.4",
"kind": "patch",
"published_at": "2026-06-18T17:50:45Z"
},
{
"tag": "v0.47.3",
"kind": "patch",
"published_at": "2026-06-18T06:41:00Z"
},
{
"tag": "v0.47.2",
"kind": "patch",
"published_at": "2026-06-17T19:22:37Z"
},
{
"tag": "v0.47.1",
"kind": "patch",
"published_at": "2026-06-17T16:13:02Z"
},
{
"tag": "v0.47.0",
"kind": "minor",
"published_at": "2026-06-15T23:35:20Z"
},
{
"tag": "v0.46.0",
"kind": "minor",
"published_at": "2026-06-11T14:24:29Z"
},
{
"tag": "v0.45.0",
"kind": "minor",
"published_at": "2026-06-09T03:29:09Z"
},
{
"tag": "v0.44.0",
"kind": "minor",
"published_at": "2026-04-18T21:26:47Z"
},
{
"tag": "v0.43.0",
"kind": "minor",
"published_at": "2026-03-24T04:16:07Z"
},
{
"tag": "v0.42.2",
"kind": "patch",
"published_at": "2026-03-21T15:20:07Z"
},
{
"tag": "v0.42.1",
"kind": "patch",
"published_at": "2026-03-21T03:30:57Z"
},
{
"tag": "v0.42.0",
"kind": "minor",
"published_at": "2026-03-10T00:07:06Z"
},
{
"tag": "v0.41.0",
"kind": "minor",
"published_at": "2026-03-01T02:01:26Z"
},
{
"tag": "v0.40.0",
"kind": "minor",
"published_at": "2026-02-28T06:55:18Z"
},
{
"tag": "v0.39.0",
"kind": "minor",
"published_at": "2026-02-27T07:07:24Z"
},
{
"tag": "v0.38.0",
"kind": "minor",
"published_at": "2026-02-19T17:16:27Z"
},
{
"tag": "v0.37.0",
"kind": "minor",
"published_at": "2026-02-15T20:54:50Z"
},
{
"tag": "v0.36.0",
"kind": "minor",
"published_at": "2026-02-14T22:06:07Z"
},
{
"tag": "v0.35.0",
"kind": "minor",
"published_at": "2026-02-14T19:10:45Z"
},
{
"tag": "v0.34.0",
"kind": "minor",
"published_at": "2026-02-11T04:54:24Z"
},
{
"tag": "v0.33.0",
"kind": "minor",
"published_at": "2026-02-10T02:36:43Z"
},
{
"tag": "v0.32.0",
"kind": "minor",
"published_at": "2026-02-09T04:18:37Z"
},
{
"tag": "v0.31.0",
"kind": "minor",
"published_at": "2026-02-07T23:57:11Z"
},
{
"tag": "v0.30.0",
"kind": "minor",
"published_at": "2026-02-06T17:17:10Z"
},
{
"tag": "v0.29.0",
"kind": "minor",
"published_at": "2026-02-03T00:31:37Z"
},
{
"tag": "v0.28.1",
"kind": "patch",
"published_at": "2026-02-01T01:14:53Z"
},
{
"tag": "v0.28.0",
"kind": "minor",
"published_at": "2026-01-30T20:06:39Z"
},
{
"tag": "v0.27.0",
"kind": "minor",
"published_at": "2026-01-30T17:21:27Z"
},
{
"tag": "v0.26.0",
"kind": "minor",
"published_at": "2026-01-30T00:08:17Z"
},
{
"tag": "v0.25.0",
"kind": "minor",
"published_at": "2026-01-29T05:25:05Z"
},
{
"tag": "v0.24.0",
"kind": "minor",
"published_at": "2026-01-28T21:20:24Z"
},
{
"tag": "v0.23.0",
"kind": "minor",
"published_at": "2026-01-26T21:00:09Z"
},
{
"tag": "v0.22.2",
"kind": "patch",
"published_at": "2026-01-26T19:00:39Z"
},
{
"tag": "v0.22.1",
"kind": "patch",
"published_at": "2026-01-26T18:40:39Z"
},
{
"tag": "v0.22.0",
"kind": "minor",
"published_at": "2026-01-25T21:09:47Z"
},
{
"tag": "v0.21.0",
"kind": "minor",
"published_at": "2026-01-24T01:35:57Z"
},
{
"tag": "v0.20.0",
"kind": "minor",
"published_at": "2026-01-21T21:34:59Z"
},
{
"tag": "v0.19.0",
"kind": "minor",
"published_at": "2026-01-21T19:15:15Z"
},
{
"tag": "v0.18.0",
"kind": "minor",
"published_at": "2026-01-20T22:48:34Z"
},
{
"tag": "v0.17.0",
"kind": "minor",
"published_at": "2026-01-20T06:08:33Z"
},
{
"tag": "v0.16.0",
"kind": "minor",
"published_at": "2026-01-20T05:41:44Z"
},
{
"tag": "v0.15.1",
"kind": "patch",
"published_at": "2026-01-19T20:19:42Z"
},
{
"tag": "v0.15.0",
"kind": "minor",
"published_at": "2026-01-18T04:18:22Z"
},
{
"tag": "v0.14.0",
"kind": "minor",
"published_at": "2026-01-18T03:12:06Z"
},
{
"tag": "v0.13.0",
"kind": "minor",
"published_at": "2026-01-17T22:38:38Z"
},
{
"tag": "v0.12.3",
"kind": "patch",
"published_at": "2026-01-15T06:41:31Z"
},
{
"tag": "v0.12.2",
"kind": "patch",
"published_at": "2026-01-15T01:46:10Z"
},
{
"tag": "v0.12.1",
"kind": "patch",
"published_at": "2026-01-15T00:11:34Z"
},
{
"tag": "v0.12.0",
"kind": "minor",
"published_at": "2026-01-14T20:56:45Z"
},
{
"tag": "v0.11.0",
"kind": "minor",
"published_at": "2026-01-13T18:52:11Z"
},
{
"tag": "v0.10.0",
"kind": "minor",
"published_at": "2026-01-13T16:53:33Z"
},
{
"tag": "v0.9.0",
"kind": "minor",
"published_at": "2026-01-11T05:42:40Z"
},
{
"tag": "v0.8.0",
"kind": "minor",
"published_at": "2026-01-10T15:16:16Z"
},
{
"tag": "v0.7.0",
"kind": "minor",
"published_at": "2026-01-08T04:04:41Z"
},
{
"tag": "v0.6.0",
"kind": "minor",
"published_at": "2026-01-08T00:05:06Z"
},
{
"tag": "v0.5.0",
"kind": "minor",
"published_at": "2026-01-07T15:35:05Z"
},
{
"tag": "v0.4.26",
"kind": "patch",
"published_at": "2026-01-06T23:15:45Z"
}
],
"recent_commits": [
{
"oid": "b739b10255e71f39ef7490ef0177e556db5b285c",
"body": "Detect damaged databases before explicit or automatic sync, roll back pull batches when any event fails, and harden snapshot replacement against stale WAL generations and concurrent connections. Add integrity, cursor-preservation, and bootstrap regression coverage.\\n\\nRefs td-98f8e4\\n\\n🤖 Generated with Codex\\n\\nCo-Authored-By: Codex <noreply@openai.com>",
"is_bot": false,
"headline": "fix(sync): fail closed on SQLite corruption",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T19:48:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2950043244beffba102cc21d6452b4b70239d23e",
"body": "…c50)\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: per-project sync enablement model + override precedence (td-7d6…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T19:24:23Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "31ec01b0f8234b1d216b7a0609c349b084122e1e",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: always-available 'td sync status' diagnostics (td-78b482)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T19:22:05Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2d5fab4c40e574135879f8530078c5332f66907d",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: avoid DB opens on hot path in stranded-sync warning (td-da622d)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T19:22:05Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "bbc6b97dbc2e94d5d2271d73bf76be75b1293b5e",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: warn when a sync-configured project has autosync off (td-da622d)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T19:22:05Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b9567324f7070fda74902e52b195916b31c5ff40",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add global sync kill-switch in config.json (td-735875)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T19:22:05Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "cea7f3761a486fb07c819ef44030b5af22efbe4f",
"body": "…to override (td-a4c721)\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: gate autosync on per-project sync config; demote sync_autosync …",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T19:22:05Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "4e57e5e52b6136ed3b0491730cd49b16b5285df1",
"body": "ListMembers now joins users.email and the user-facing GET\n/v1/projects/{id}/members response includes it, so clients can show a\nhuman-readable identity instead of the raw user_id.\n\nUpdateMemberRole now runs in a transaction and rejects demoting the last\nremaining owner (mirrors RemoveMember's existi\n[…]\nd) so a project can\nnever be left without an owner. The update/remove handlers map the\nlast-owner guard to 409 Conflict with code \"last_owner\".\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "members: expose email in list; block demoting the last owner",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T19:22:05Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "f8d290ea2a0d54684c774934c67d08039aeb778b",
"body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: ignore .nightshift-plan artifacts",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T16:27:45Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "ba4f88dd9137eeb862705a0018b93dfd53903082",
"body": "Root cause: the DB was opened without a modernc _time_format param, so its\ndefault writer serialized every time.Time with time.Time.String() -- emitting a\nmonotonic-clock suffix (m=+...) and a zone name (PDT) that the driver cannot\nparse back. This corrupted timestamps DB-wide but only surfaced on t\n[…]\nso a\n developer's shell no longer breaks feature tests.\n\nIndependently reviewed. go test ./... green (33 packages), go vet clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: normalize SQLite timestamp serialization (td session lookup crash)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T15:57:50Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "51a7b0164f09b746282976d4305c10fe5972b14c",
"body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: cut v0.51.1 changelog (handoff stdin fix)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-18T15:00:11Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "a110ef95c98bdff3f9af65eb489fed5d08e2a86f",
"body": null,
"is_bot": false,
"headline": "Fix handoff",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-07-17T23:28:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0f39dfebff89079b9fdb5d3bfd46944008ef07f2",
"body": "Summarize the session/worktree state, sync hardening, and handoff autosync fixes included in the v0.51.0 release.\n\nGenerated with Codex\n\nCo-Authored-By: Codex <noreply@openai.com>",
"is_bot": false,
"headline": "docs: cut v0.51.0 changelog",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T04:04:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2a0c1734ae404dcd8f7ee90a1f159456137350fa",
"body": "Skip startup auto-sync for handoff so progress capture does not wait on a pre-command pull. If the post-mutation push fails, leave events pending and warn without attempting an immediate pull against the same unhealthy endpoint.\n\nGenerated with Codex\n\nCo-Authored-By: Codex <noreply@openai.com>",
"is_bot": false,
"headline": "fix: reduce handoff autosync stalls",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T04:03:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "95251d30c2027e565039e40abc43d5a095dd5e4e",
"body": null,
"is_bot": false,
"headline": "feat: use session_state for serve focus (td-dd7a11)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T03:30:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "666c80761a0c999325b6bccefe133a6ef279b68f",
"body": null,
"is_bot": false,
"headline": "fix: call show RunE from resume (td-e2f1ab)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T03:20:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6c6feac9abf7e894544908f571fe6e2efa70e633",
"body": null,
"is_bot": false,
"headline": "feat: use session_state for CLI current state (td-e2f1ab)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T03:13:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1577514f506e9b7b8ef599ad55c0fc2c376a58d2",
"body": null,
"is_bot": false,
"headline": "feat: add local session state store (td-3d427b)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T02:58:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "856330cd35d01ff44c336d8f9819098818ac3079",
"body": null,
"is_bot": false,
"headline": "fix: scrub local-only fields from sync conflicts (td-83cfc9)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T02:48:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d43f359671c1ec16eeb30266daec1ced60926a4a",
"body": null,
"is_bot": false,
"headline": "fix: scrub local-only fields from server sync events (td-83cfc9)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T02:40:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fd18a34c30f937eab74be67fc32b7a7789c39d09",
"body": null,
"is_bot": false,
"headline": "fix: keep worktree metadata local in work session sync (td-83cfc9)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T02:31:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ee5984d83e66d2bc1b9e857710b7dd0ab58279e6",
"body": null,
"is_bot": false,
"headline": "feat: add worktree identity to sessions (td-83cfc9)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T02:23:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cc5dc646a22c748a2065b2b937d9e6e6d7417867",
"body": null,
"is_bot": false,
"headline": "docs: plan session-scoped current state (td-af80e9)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T02:13:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fceccc7afa87fe30da52973caaa78d172af359a9",
"body": "…anges\n\nPost-mutation auto-sync made a single push attempt with a 5s timeout and\nswallowed failures to slog.Debug, so a transient blip left the change\nunsynced until the next td command or the 5m monitor tick — the main source\nof \"it didn't show up in td-watch\" inconsistency.\n\n- pushBatchWithRetry: \n[…]\nt).\n\nTests cover retry recovery, budget cutoff, timeout restoration, no-retry on\nunauthorized, and events left pending when the server is down.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: retry auto-sync push with bounded backoff + surface stranded ch…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-21T01:39:38Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "52ef3fae6d7b34b8fab05e5c291ef5ac06deadca",
"body": "…a616c2)\n\nThe reviewer examples used 'td approve <id> --record-only', but --record-only\nis hard-rejected in trusted mode (the project default; cmd/review.go:648-655).\nAn agent on a default/fresh project that copy-pasted those examples would hit a\nfatal error.\n\nDefault trusted-mode examples now use a\n[…]\n-record-only is shown only under an\nexplicit delegated-mode caveat, mirroring the CLAUDE.md review-model section.\n\n🤖 Generated with Claude Code\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: fix record-only examples to plain approve for trusted mode (td-…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T23:08:45Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "ccd4a246e4ac4be53f8b59157b76bbeab39ae479",
"body": "…T_ID) (td-a616c2)\n\nAdd docs/multi-agent-sessions.md documenting the three routes for giving\nsub-agent contexts independent td sessions so delegated reviews are recorded\nas genuinely independent (Failure Mode #6):\n\n1. TD_CONTEXT_ID (recommended, shipped in td-64dc09) - feeds the session\n lookup ke\n[…]\n.\n3. Worktree isolation (forthcoming, not yet implemented).\n\nAdd a short pointer in CLAUDE.md's review-model section linking to the\nfuller doc.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: document orchestrator sub-agent session independence (TD_CONTEX…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T23:05:50Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b86cf159675f9d88aa1516ce3a08d8b04815338e",
"body": "Canonical identity model: explicit implementer/reviewer role declaration\nreplacing inferred-from-session-identity independence. Defines command\nsurface, issue_role_delegations schema, reviewpolicy precedence guard\n(declared role wins, fall back to session inference), migration story\nfrom shipped con\n[…]\nwork.\nAdditive and precedence-based so the two identity paths are one layered\nsystem, not two half-supported ones. Stubs follow-up tasks D1-D7.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: design spec for td delegate explicit role declaration (td-d7fd80)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T22:54:36Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "66344fd54c8e089bb66cd0017a8bcd4aa64890ea",
"body": "validateTitle now returns (warning, err): a too-short title produces a\nnon-fatal warning and creation proceeds, while generic titles and\nover-max titles remain hard errors. The warning is surfaced via the\nexisting emitWarn helper (human mode only; silent in --json so scripts\nget a clean success envelope). Updated cmd/create_test.go accordingly.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: downgrade title min-length from rejection to warning (td-e76379)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T22:47:45Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8e0ad64f2cd27e48142d7f8be829bafb42815449",
"body": "When td review auto-creates a handoff because none exists, synthesize the\nDone/Decisions fields from the issue's substantive session logs instead of\nwriting an empty placeholder. Routine workflow logs (Started work, Submitted\nfor review, etc.) are filtered out via the existing isSubstantiveReviewCon\n[…]\no the minimal placeholder when there are no usable logs, and\nwaives the auto-handoff entirely for --minor issues (which already bypass\nreview).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: synthesize auto-review handoff from session logs (td-713b57)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T22:42:33Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "34252e7ebf0820f969586a520c7bf03d05ad25f3",
"body": "Promote a context dimension into the session lookup key so distinct\nsub-agent contexts that share one process/branch/checkout no longer\ncollapse into a single session (Failure Mode #6).\n\nWhat changed:\n- New optional env var TD_CONTEXT_ID feeds a dedicated matching key.\n session.matchContextID() ret\n[…]\netSessionByIdentity context keying (db); distinct sessions for\ndiffering TD_CONTEXT_ID, empty-context reuse, and same-context refind\n(session).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: key sessions by context_id for sub-agent independence (td-64dc09)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T22:37:27Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "1032097899372a4b244a23de13d657c7ca099f65",
"body": "Record planning decisions (lean scope, context_id-keying-as-mechanism +\ntd delegate as canonical successor, session_state local-only) and two\ncode-grounding corrections (handoff gate already auto-creates; title min\nalready configurable).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: scope session/worktree flow lean phase into epic (td-124499)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T22:25:51Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "250c30c8941a0892c65ca9a84afa04a1b493db6a",
"body": "… (td-70916d)\n\nA sync re-pulls the client's own just-pushed events to keep server_seq\nconvergent. Replaying them in order can transiently overwrite newer local\nstate (identical-payload logs; an issue creation event landing on a later\nlocal close) before a subsequent event restores it. These self-rep\n[…]\n. Independently reviewed; full suite green.\n\n(Also picks up a pre-existing gofmt alignment fix in the same file.)\n\n🤖 Generated with Claude Code\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: suppress sync conflict false-positives from self-authored events…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T22:07:27Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "0bbecff8d5224c56b27cd74ab3b500b9a36ea686",
"body": "…scope enforcement)\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: changelog for v0.50.0 (project slugs, invitations, web signup, …",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T21:45:11Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "82137dbeea8cb7c5fb0a4f40be03c6a619437957",
"body": "…-2df74a)\n\nBackfill no longer consumes slug namespace for soft-deleted projects;\nadmin project API now returns slug for parity with the user API; document\nstable-slug-on-rename and the p_ unicode-fallback edge case.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: skip soft-deleted in slug backfill, expose slug on admin API (td…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T21:29:55Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6ece85d33ff7a1b6e232c542119313ee2a089601",
"body": "Stored slug column + unique index on projects; slugify matching td-watch;\ngenerate on create, idempotent backfill for existing rows; expose slug on\nthe project API responses. Enables stable canonical /projects/<slug> URLs.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add first-class unique project slugs (td-2df74a)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T21:16:16Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c5a3f78fcae7b2c16701438ce9c8ec5e85358504",
"body": null,
"is_bot": false,
"headline": "Clarify sync project access guidance",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T19:41:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7870ac9efdd54b0d25f7ec5d9f6b594e4dac9539",
"body": "…ommendations\n\nCaptures the session issue hit during the --json epic orchestration: Task-tool\nsub-agents share the orchestrator's session (same branch + terminal fingerprint\n+ worktree), so independent review can't be recorded and every close is forced\nto --self-review.\n\n- Failure Mode #6: why sub-a\n[…]\noff, relax input-validation gates, plus a\n what-not-to-loosen guardrail\n- New near-term tasks; recommendation sequenced to land Phase 2b first\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: add sub-agent session-collapse failure mode + aged-controls rec…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T19:40:20Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "57a1e245c66d9b5e218a3e62486443a89e6eef3f",
"body": null,
"is_bot": false,
"headline": "docs: clarify direct member invite wording (td-8b0b31)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T19:33:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "69d33b03a12826ac5546cfbef3eca53e2dc6bd5f",
"body": "…ts (td-b4f7cd)\n\nAdd a 'JSON output (--json)' section to docs/guides/cli-commands-guide.md\ndocumenting the global persistent flag, the two success envelopes\n(EmitIssue / EmitResult), the error envelope, NDJSON bulk output, the\nknown exceptions (query --output, the JSONL commands, show --format\njson)\n[…]\n--json\nmode and carries the expected action/id, plus the JSON error envelope\nshape (close) and RunE-returns-error on missing id (log, handoff).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: document --json contract; add cross-command JSON regression tes…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T19:28:14Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "327f21a637984da9e7635a875f8084c9dfd91294",
"body": "…iew JSON; fix JSONError escaping (td-575c78)\n\nThree pieces of work, all under td-575c78:\n\n1. Fix output.JSONError escaping: replaced the hand-rolled fmt.Printf(\"%s\")\n envelope with a json.Encoder (SetEscapeHTML(false)) over a small error\n struct. The previous form produced invalid JSON when a m\n[…]\nnged.\n\nUpdated TestWsCurrentFlags and TestRejectJSONShapeUnchanged to reflect the\ninherited-flag wiring. go build ./... and go test ./... pass.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: collapse local --json onto persistent flag; add approve/rev…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T19:14:35Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "9101aa36109799453d1a0b2872bc23b06f603732",
"body": "closeCmd now honors the persistent --json flag via jsonMode(cmd). In JSON\nmode it re-fetches the closed issue and emits output.EmitIssue(\"closed\",\nissue, extra) where extra carries session plus any self_close_exception,\nadmin reason, cascaded_parents, and unblocked_dependents. All human\nCLOSED/casca\n[…]\nelope, unchanged human\noutput, JSON error on not-found, and a regression guard locking the\nreject --json key set to {id,status,action,session}.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add --json to close; preserve review-family JSON shape (td-6f9e0b)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T18:59:56Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "363b4cefed69b073f7d9d311599a1aea08421c68",
"body": "Co-Authored-By: Codex <codex@openai.com>",
"is_bot": false,
"headline": "feat: allow invited users through web signup (td-ff9d4d)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T18:50:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "81d43a01795ce79d8a245f94ae4c9fc0a14bbf3a",
"body": "…tions (td-862b42)\n\nWire the global --json persistent flag into the transition and relationship\ncommands, following the create.go (c0f967f) and update/start/log/handoff\n(edab30e) pattern:\n\n- unstart: emit output.EmitIssue(\"unstarted\", issue, nil) per id, re-fetching\n the now-open record (NDJSON in \n[…]\n\nTests: cmd/transition_json_test.go asserts the json envelope keys plus a db\nround-trip and unchanged human output across all the new commands.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add --json to unstart/defer/block/reopen/unblock/link/note muta…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T18:48:46Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "cbae9122ee4c1b7575f05850de3b34b6846e4eaa",
"body": "Co-Authored-By: Codex <codex@openai.com>",
"is_bot": false,
"headline": "fix: close invitation backend edge cases (td-274e59)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T18:44:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "edab30e2ac0d7541a55878a3fc1bd8f380e4e3b7",
"body": "Wire the global --json persistent flag into the core mutating commands,\nfollowing the create.go pattern (commit c0f967f):\n\n- update: in json mode emit output.EmitIssue(\"updated\", issue, nil),\n re-fetching the post-update record. One JSON object per id (NDJSON) in\n the bulk case.\n- start: single st\n[…]\nest.go covers json envelopes (expected keys + db\nround-trip), bulk start NDJSON shape, and unchanged human output for\nupdate/start/log/handoff.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add --json to update/start/log/handoff (td-7b9ddf)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T18:38:15Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e5f4125a7886e96d26426fb3c1c2cfbb6fd5c37a",
"body": "Co-Authored-By: Codex <codex@openai.com>",
"is_bot": false,
"headline": "feat: add project invitation backend (td-274e59)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T18:37:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c0f967fac69412cb6ffe1ac50ec9152713e42c39",
"body": "Wire the global --json persistent flag into create/add (and epic create,\nwhich delegates to create's RunE):\n\n- Success path: when jsonMode(cmd), emit output.EmitIssue(\"created\", issue,\n nil) — the full created *models.Issue with the new id — instead of the\n human \"CREATED <id>\" line. Human output \n[…]\nr\":{...}}` on stdout.\n\nTests: cmd/create_json_test.go covers json full-issue envelope, unchanged\nhuman output, and epic-create json delegation.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add --json to create/add returning full issue (td-0a8c33)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T18:28:23Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "98bb6144fef568e423a569b61797779007f84c27",
"body": "Co-Authored-By: Codex <codex@openai.com>",
"is_bot": false,
"headline": "feat: allow web signup magic links (td-7b6135)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T18:24:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c7fdd88fc341bf154826f61e8fe9141f8ff855b2",
"body": "…lpers (td-d0f2ac)\n\nAdds infrastructure for consistent JSON output across td commands without\nchanging any existing command's output behavior:\n\n- cmd/root.go: register persistent --json flag; in Execute() emit a JSON\n error envelope (output.JSONError) to stdout before the unknown-flag /\n workflow-\n[…]\nal/inherited/missing/nil), and the os.Args error-path fallback.\n\nWiring --json into individual commands is handled by separate follow-up tasks.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: JSON output foundation — persistent --json flag + emit/error he…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-20T18:17:59Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "8ffe752fecd7fb47d3ba3fd8f9134482dc69f0e9",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "test: scope-enforcement matrix incl. admin proxy paths (td-336b32)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T17:00:16Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2fb5781246337529d63bb3e3704edd0aa1d1e158",
"body": "…d-f0bf76)\n\nAdds projectScopeAllowed() helper and applies it at all three project-route\nenforcement sites: requireProjectAuth (middleware.go), requireProjectMembership\n(project_middleware.go), and the flat GET/POST /v1/projects routes via a new\nrequireProjectScope wrapper (server.go). Admin routes and requireAuth itself\nare untouched. go test ./internal/api/ passes.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: enforce sync scope on project routes, preserving admin proxy (t…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T16:53:29Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "37336760f714d356e9c411d96674f3ac5e32e140",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add HasAnyScope helper (td-250d27)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T16:48:46Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8d7e5706915aaab52bd49c95b7d05e4ad8960954",
"body": "The auth rate-limit middleware applied the strict SYNC_RATE_LIMIT_AUTH (10/min)\nto every /v1/auth/* path, but the device flow advertises a 5s poll interval\n(~12/min). A real CLI login polls for the whole approval window, so it hit 429\nbefore the user could click the email. Poll endpoints now use a s\n[…]\nigher limit (RateLimitOther), keeping the strict limit on the\nstart/exchange/approve endpoints. Regression test added. Web login is unaffected.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: give device-login poll endpoints a separate, higher rate limit",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T16:30:00Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "304738d81e8bc6f0ae8ba3031edfec852d5af76b",
"body": "…L (td-d5f5ef)\n\nCloudflareSender consumes EmailConfig.BaseURL as the Cloudflare REST API base\n(default api.cloudflare.com), but the server wiring fed it AuthEmailBaseURL\n(SYNC_EMAIL_BASE_URL=https://sync.haplab.com), so email sends POSTed to td-sync's\nown host -> 404 -> login emails failed in prod. \n[…]\nEmailConfig() that does not\nset it, and add a regression test. SYNC_EMAIL_BASE_URL remains used by the auth\nhandlers for magic-link generation.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: stop mapping SYNC_EMAIL_BASE_URL into the Cloudflare API base UR…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T15:55:37Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "325274e83a586bb9efdb661f13ca2302cf94544e",
"body": "… was crash-looping\n\nThe prod override mounted litestream.prod.yml (S3 replica) over /etc/litestream.yml,\nbut with no S3 bucket (backups disabled) litestream exits with \"bucket required for\ns3 replica\" and the container crash-loops. Drop the mount so the image's default\nfile-replica config is used (starts cleanly). Re-add the mount only with a real\nLITESTREAM_S3_BUCKET to enable S3 backups.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(deploy): don't mount S3 litestream config in prod (backups off) —…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T15:41:00Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "3838bd0cc06371975c6b77583c5718f9f9e4ed0d",
"body": null,
"is_bot": false,
"headline": "docs: map td session worktree flow",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T15:29:18Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e44bf9f4a93c6632b9051dfbe04e53884cc1cfea",
"body": null,
"is_bot": false,
"headline": "fix(deploy): fail secure auth cutover if legacy login remains live",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T15:29:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2cca4213514b957023ba268c4eb0e9ca558f6334",
"body": "…th validation, health gate\n\n- backups optional (LITESTREAM_ENABLED gate) so a deliberate no-backups prod deploys\n- prod fails closed if email/auth config missing (SYNC_EMAIL_PROVIDER + CLOUDFLARE_* +\n SYNC_AUTH_WEB_CALLBACK_URL) while legacy auth is off — prevents a login-locked deploy\n- health ch\n[…]\nalthz with timeout and exits non-zero on failure (no more\n false \"success\" on a down server); post-deploy check asserts legacy auth is 410/404\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(deploy): harden prod deploy.sh — optional backups, fail-closed au…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T15:02:11Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "fb1327a4056d9d9b3ea3f5242f52012b2914d576",
"body": "Replace the disabled legacy /v1/auth/login/start + /auth/verify endpoints in\ntest/e2e/harness.go and scripts/e2e-sync-test.sh with the device PKCE flow:\ngenerate PKCE -> device/start -> read magic link via GET /internal/dev/last-email\n(memory provider) -> approve -> poll. Provision users up front vi\n[…]\nync_cli feature flag so the full convergence test passes end-to-end.\n\ngo test ./test/e2e/ (non -short) passes; scripts/e2e-sync-test.sh passes.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "test: migrate e2e harness to device PKCE login flow (td-b274ed)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T15:00:12Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "59215575a9e803bb7ab6f96b1e42adbad41d780b",
"body": "…ner (td-d255db)\n\nThe prod compose override enumerated container env explicitly and omitted all\nPhase 1-4 email/auth vars, so --env-file values never reached the container —\nemail send + web/device auth would be dead in prod. Add the email/auth vars via\n${VAR} substitution. SYNC_DEV_EMAIL_INSPECT intentionally NOT passed (dev-only).\nVerified all 9 keys resolve via `docker compose ... config`.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(deploy): pass email + secure-auth env vars to prod td-sync contai…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T14:52:53Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "ed892becf27cd694045ce1ea10ab94d6f00e2c0f",
"body": "…td-d55391)\n\nDouble-gated (SYNC_DEV_EMAIL_INSPECT=true AND *email.MemorySender provider);\nreturns 404 otherwise. Inert in prod, which uses the cloudflare provider.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: dev-only GET /internal/dev/last-email to read last magic link (…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T14:49:18Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "5d9b50fbc9c8d3e7070cdd758d35597f73873c61",
"body": "Cloudflare's Email Sending API rejects reply_to as {\"address\": ...} with\nemail.sending.error.invalid_request_schema; it must be a plain email string.\nProven via live sends against the real API. The httptest unit test asserted\nthe wrong (object) shape, masking the bug — updated to assert a string.\nWithout this, no login email would send in production.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: send Cloudflare reply_to as a string, not an object (td-ed1ade)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T14:31:47Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "420c460225e6b1945ec49d25bc0f1785f62026f4",
"body": "Replace the old \"verification URL + 6-character code\" description in\nsync-client-guide.md and sync-setup-guide.md with the new email-approval\nflow: a local PKCE verifier is generated, only the S256 challenge is sent,\nthe server emails a one-time approval link, and the login completes only\nafter the link is clicked. No code is shown in the terminal.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: describe CLI email-approval (PKCE) login flow (td-3966bb)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T14:31:43Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6f4b34d6047c0ebc70c4058505ec43e025b96a87",
"body": "Drives the real syncclient + PKCE helper against a live in-process api\nserver (httptest.Server over srv.routes()) with a MemorySender:\n\n- FullFlow: GeneratePKCE -> DeviceStart -> read magic link from the\n in-process MemorySender -> approve -> DevicePoll yields a ~365-day key;\n the key authenticate\n[…]\n returns\n 401 invalid_verifier and no key (PKCE binds the login to this process).\n- UnknownEmailNoKey: non-enumerating start, never completes.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "test: end-to-end CLI PKCE device-login integration tests (td-89e8b8)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T14:30:28Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a461dec894b26639b46b936603815f68f08bd3ff",
"body": "`td auth login` now generates a local PKCE verifier, sends only the S256\nchallenge via DeviceStart, and prints \"Check your email and click the link\nto approve this login\" — no user code and no self-approval URL are shown.\nIt polls DevicePoll with device_code + verifier at the server interval until\nc\n[…]\nm the\nserver. The returned 365-day key is saved to auth.json in the unchanged\nformat. device_name is derived from the hostname (td-cli@<host>).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: td auth login uses PKCE email-approval device flow (td-1d9cfc)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T14:29:02Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "f38cb43d14e8e6164d68d5394479c6bbd9691299",
"body": "GeneratePKCE() produces a 32-byte crypto/rand verifier (base64url no-pad)\nand Challenge = base64.RawURLEncoding(SHA-256(verifier)), exactly matching\nthe S256 verification in handleDevicePoll. Unit tests assert the S256\nrelationship, uniqueness across calls, and RFC 7636 verifier length.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add PKCE helper for CLI device login (td-011205)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T14:27:50Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "ef54ad863ee523654cd82b6c205855252c7c9d93",
"body": "Add DeviceStart(email, codeChallenge, method, deviceName) and\nDevicePoll(deviceCode, codeVerifier) hitting the new non-enumerating\n/v1/auth/device/{start,poll} endpoints, plus DeviceStartResponse and\nDevicePollResponse types mirroring internal/api/auth.go. The legacy\nLoginStart/LoginPoll methods are left in place.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add syncclient DeviceStart/DevicePoll PKCE methods (td-df552e)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T14:27:42Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "7b4f76663afe832e310d8776593bb2f8f53e2423",
"body": "…49f)\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: run CleanupExpiredChallenges in background cleanup loop (td-b78…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T06:11:07Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "217a97f4bb392eb6b8bdd1eb2971d990cc31a1ae",
"body": "…H (td-8cade5)\n\nWhen SYNC_LEGACY_DEVICE_AUTH is unset or false (the default), POST\n/v1/auth/login/start and /v1/auth/login/poll return 410 Gone with an\nendpoint_disabled error code, and GET/POST /auth/verify return 404.\nSet SYNC_LEGACY_DEVICE_AUTH=true (or =1) to re-enable the old flow for\nlocal/dev use. Existing legacy-endpoint tests opt in via\nsrv.config.LegacyDeviceAuth = true.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: gate legacy device-auth endpoints behind SYNC_LEGACY_DEVICE_AUT…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T06:08:50Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b64eb0bb69f2faf83890b97f0578e699972b2be9",
"body": "Implements D4 of the CLI device login flow:\n\n- GET /auth/device/approve: verifies selector.secret token via\n VerifyAndMarkDeviceChallengeVerified (secret hash check + atomic\n pending->verified transition), sets Referrer-Policy: no-referrer, logs\n AuthEventDeviceVerified, serves HTML success/error\n[…]\ng full flow, poll-before-approve, wrong secret, wrong verifier,\n double-issue prevention, link-reuse, and unknown-device-code non-enumeration.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add device approval page + poll endpoint with PKCE (td-765a96)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T06:01:23Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "36db2cb5e502a9e8fb1b2cdc2151d8067d797eca",
"body": "Implements the first half of the CLI device login flow. Validates email,\ncode_challenge (required), and code_challenge_method (must be S256). For\nknown users, creates a device_login email challenge storing DeviceCodeHash,\nCodeChallenge, and CodeChallengeMethod, then sends an approval email to\nAuthEm\n[…]\n) with no challenge created and no email sent;\nAuthEventEmailSuppressed is recorded. Rate limit (1/min per email) also\nreturns the generic 200.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add POST /v1/auth/device/start with PKCE challenge (td-7501b9)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T05:54:06Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "2bbc350288ee80d8251a59b3b83839b12406b89c",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add POST /v1/auth/web/exchange (30-day web key) (td-1205ff)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T05:48:56Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8c9c67e7a77791caa599a090b32074ca7848559b",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add POST /v1/auth/web/start email login endpoint (td-c40207)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T05:44:09Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "0a1ff8aecf1a586b042b1bb72ebb3a68fff91ac4",
"body": "…55a)\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: wire EmailSender into server + add auth event constants (td-144…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T05:39:42Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b251c5c48447e8304a3c22840f13b209f8764522",
"body": "…-54cf93)\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: document email provider config in env templates + ops guide (td…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T04:37:44Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c33160e5a848f1f73a469343de93d79cd53ac403",
"body": "CloudflareSender.SendLoginLink POSTs to the Cloudflare Email Sending\nREST API with Bearer auth and the CF envelope JSON shape. Validates\nrequired config fields at construction time. API token and magic link\nbody content are never logged or surfaced in errors.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: implement Cloudflare email REST sender (td-d36311)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T04:34:46Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b13a2c2fd74e4d6d1ccc96880fcbce415e58980b",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add EmailSender interface + memory/log providers (td-b74d04)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T04:31:51Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "ac3bc124d71469c1c8d358302b69ca72d8705236",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add email provider config + startup validation (td-43904b)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T04:29:01Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b9b861fbc35e05648d31ab427414f44520e9a6a3",
"body": "…td-054083)\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: drop misleading no-op BEGIN IMMEDIATE in ConsumeChallenge (…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T04:26:59Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "197c0d971701f741d555314ec2ef9e8853eaf359",
"body": "Implements CreateEmailChallenge, LookupChallenge, ConsumeChallenge,\nLookupChallengeByDeviceCodeHash, and CleanupExpiredChallenges for the\nauth_email_challenges table (migration v4). Only SHA-256(secret) is stored;\nplaintext token is never persisted. ConsumeChallenge is atomic and single-use.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add auth email challenge store methods (td-054083)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T04:23:47Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6743b7a6c9e8c905e3ab1c0ad23cc716f39ea4a9",
"body": "Bump ServerSchemaVersion 3->4 and append migration v4 that creates the\nauth_email_challenges table with all columns, constraints (purpose CHECK\nincludes admin_login), and three indexes. Update TestMigrationV3_SchemaVersion\nto use a >= 3 assertion since a fresh DB now reaches v4.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add auth_email_challenges migration v4 (td-5531d1)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T04:19:18Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "a7f9f0323b51dbfa6cc3bab9d29684f5e67615d5",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add admin revoke-key CLI subcommand (td-db323f)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T04:17:02Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b499610ceab17cd0a71558f6f8011f6157da7042",
"body": "DELETE /v1/admin/users/{id}/keys/{keyID} gated on new admin:write:users scope.\nReturns 204 on success, 404 on missing user or key, 403 on auth failure.\nRecords key_revoked auth event with admin_user_id + key_id metadata (no key material).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add admin key revocation endpoint (td-d606a9)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T04:14:53Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "0ecf00bb8df75ba0a9d0cbf94728207f1ce07b86",
"body": "Add AdminRevokeAPIKey(keyID string) error to internal/serverdb/apikeys.go\nthat deletes any api_keys row by ID with no user_id constraint. Returns\nErrNotFound (new package-level sentinel in serverdb.go) when RowsAffected==0\nso HTTP handlers can map to 404. Tests cover successful revoke, non-existent\nkey, and that VerifyAPIKey returns nil after admin revocation.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add AdminRevokeAPIKey to serverdb (td-787c8f)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T04:10:29Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "42961b02e161d3e5318e709c67fcc994a4b4d41f",
"body": "Board and issue-list responses blanked the heavy text fields (description,\nacceptance) that those views never render off store-hydrated issues; the\ndetail endpoint refetches the full issue, so it's unchanged. ~42% smaller\nper issue (~1MB+ on the sidecar all-issues board), compounding with gzip.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "perf(serve): slim board/list payload — omit description/acceptance",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T03:33:42Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "5f8018c01bd2e4c6c717fbad7d7217db98355ed5",
"body": "The server builds td-sync on deploy, accumulating build cache and\ndangling images; a full disk makes nginx truncate large proxied\nresponses (caused a prod incident). Prune every deploy and report disk.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "ops(deploy): prune docker images + build cache after remote deploy",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T03:28:52Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2fcf72236513dd55640910f0544dd5270fa83bfc",
"body": "Silent failures in the batched blocker queries now emit slog.Warn so a\ndegraded board (cards missing their blocked dot) is observable, instead\nof failing silently.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(serve): log DB errors when building dependency summaries",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T00:53:36Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "df40ec777ee0b711183169bbd9a03919810929eb",
"body": "Board and issue-list responses now carry an optional dependency_summary\nwith the issue's non-closed blockers (depends_on direction), enriched\nwith title+status via two batched queries (no N+1). Detail endpoint\nunchanged. Powers the blocked-card indicator in td-watch.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(serve): include unresolved-blocker summary on board/list issues",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-19T00:37:12Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "12b000f06eb316f5716abf282cb27731cfdf4f8b",
"body": null,
"is_bot": false,
"headline": "test(sync): tolerate fast monitor autosync in e2e",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-18T17:48:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "900d142e9d85fe624126a6243e22b407504ea298",
"body": null,
"is_bot": false,
"headline": "fix(sync): cover wrapped issue update replay (td-9edf1b)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-18T17:27:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a9abb62a1001cfd9aacff6bcc2d4e252fd30e797",
"body": null,
"is_bot": false,
"headline": "sync: unwrap ReviewUndoPayload when applying remote issue events",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-18T16:12:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cecc7a016162117b5b81ac4153b2db21afb40c3d",
"body": "Add an `available_transitions` field to the issue-detail, transition, and\nPATCH responses, computed per issue+session by reusing the exact decision\nfunctions the transition endpoints enforce (validFrom + the in_review/\nnon-minor close rule + the approve review-policy decision, incl. delegated\nMode-C\n[…]\nr than a status-based guess that includes actions the endpoints reject\n(e.g. close on a non-minor in_review issue). Omitted from list payloads.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Expose per-issue available_transitions on issue responses",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-18T05:35:58Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "dc0c7e16b1754b308559ae89552dc2eaf0bc4508",
"body": null,
"is_bot": false,
"headline": "sync: auto-create session during push if it does not exist",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-18T04:04:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "847d16efeba84649bd10f9781516e854d4b2f14f",
"body": null,
"is_bot": false,
"headline": "docs: cut v0.47.2 changelog (bare-id FK 787 fix)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-17T19:19:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8af3f76490bcf1160c0c87577616235d88db093f",
"body": "handoff, comment, git-snapshot and ws-tag write paths persisted the raw\nuser-supplied issue id. When a bare id (no td- prefix) was passed, the\nstored issue_id did not match the issues(id) PK, so the FOREIGN KEY\nconstraint failed (error 787) once migration 30 enabled foreign_keys=ON.\n\nThis was misrep\n[…]\nd forms.\n\nAdds a regression test asserting bare-id writes succeed under FK\nenforcement and persist canonical ids.\n\n🤖 Generated with Claude Code\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(db): normalize issue_id before FK-constrained writes (td-25a0ae)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-17T19:19:11Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "f71909d4df14b97c3ece20cc984a449b98e82531",
"body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: cut v0.47.1 changelog (capital-letter shortcut fix)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-17T16:10:14Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8088a516fe07fd12c3b24b95923649e1733e98f9",
"body": null,
"is_bot": false,
"headline": "Merge: fix shifted capital-letter shortcuts in monitor (td-272d9b)",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-17T16:09:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ecf62b694a8f7ebfff91ad1c74a2726bcf2f5215",
"body": "KeyToString used key.Key().Keystroke(), which in bubbletea v2 renders a\nshifted printable key (e.g. shift+y => Code 'y' + ModShift) as \"shift+y\"\nrather than \"Y\". Bindings are written in textual form (\"Y\", \"?\", \"G\"), so\nevery capital-letter shortcut in the monitor (Y copy-id, C, F, G, H, I, J,\nK, N, \n[…]\n in sidecar's own keymap.\n\nTests now use realistic shifted-key input (Code + ModShift + uppercase\nText) so the regression is caught.\n\ntd-272d9b\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(monitor): match shifted capital-letter shortcuts after charm v2",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-17T16:03:05Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "62400592e7d00f9c6c221232fee797489bc367ab",
"body": "…-d31841)\n\nRewrite docs/guides/releasing-new-version.md to match the actual release\npipeline and to give automated agents a non-interactive runbook:\n\n- Correct the Homebrew story: the tap formula is bumped by the dedicated\n update-homebrew-tap job in release.yml (build-from-source, rewriting the\n \n[…]\n interactive bare `gh run watch`.\n\nAlso add the v0.47.0 CHANGELOG entry (getting-started modal first-open-only).\n\n🤖 Generated with Claude Code\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: cut v0.47.0 changelog and make release guide agent-friendly (td…",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-15T23:31:42Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "21090ce3a152f47ef46e6f53f9e596c525f29465",
"body": "The .todos/ directory holds the project's local td SQLite database and\nsession state, which should never be committed.\n\n🤖 Generated with Claude Code\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: ignore local .todos/ directory",
"author_name": "Marcus Vorwaller",
"author_login": "marcus",
"committed_at": "2026-06-15T23:31:33Z",
"body_truncated": false,
"is_coding_agent": true
}
],
"releases_count": 64,
"commits_last_year": 841,
"latest_release_at": "2026-07-18T16:00:12Z",
"latest_release_tag": "v0.51.2",
"releases_from_tags": false,
"days_since_last_push": 5,
"active_weeks_last_year": 22,
"days_since_latest_release": 6,
"mean_days_between_releases": 3.4
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": false,
"health_percentage": 42,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "github.com/marcus/td",
"exists": true,
"license": null,
"keywords": [],
"ecosystem": "go",
"matches_repo": true,
"registry_url": "https://pkg.go.dev/github.com/marcus/td",
"is_deprecated": false,
"latest_version": "v0.51.2",
"repository_url": "https://github.com/marcus/td",
"versions_count": 99,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": null,
"latest_published_at": "2026-07-18T15:57:50Z",
"latest_version_yanked": null,
"days_since_latest_publish": 6
}
]
},
"popularity": {
"forks": 27,
"stars": 232,
"watchers": 2,
"fork_history": {
"days": [
{
"date": "2026-02-05",
"count": 1
},
{
"date": "2026-02-10",
"count": 3
},
{
"date": "2026-02-12",
"count": 2
},
{
"date": "2026-02-15",
"count": 1
},
{
"date": "2026-02-17",
"count": 1
},
{
"date": "2026-02-18",
"count": 1
},
{
"date": "2026-02-23",
"count": 1
},
{
"date": "2026-02-26",
"count": 1
},
{
"date": "2026-03-03",
"count": 1
},
{
"date": "2026-03-07",
"count": 1
},
{
"date": "2026-03-09",
"count": 1
},
{
"date": "2026-03-10",
"count": 1
},
{
"date": "2026-03-21",
"count": 1
},
{
"date": "2026-03-23",
"count": 1
},
{
"date": "2026-03-26",
"count": 1
},
{
"date": "2026-03-31",
"count": 1
},
{
"date": "2026-04-02",
"count": 1
},
{
"date": "2026-04-04",
"count": 1
},
{
"date": "2026-04-17",
"count": 1
},
{
"date": "2026-04-30",
"count": 1
},
{
"date": "2026-05-12",
"count": 1
},
{
"date": "2026-05-19",
"count": 1
},
{
"date": "2026-06-16",
"count": 1
},
{
"date": "2026-06-18",
"count": 1
}
],
"complete": true,
"collected": 27,
"total_forks": 27
},
"star_history": null,
"open_issues_and_prs": 146
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": true,
"has_mcp_signal": false,
"bootstrap_files": [
"Makefile"
],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [],
"toolchain_manifests": [
"go.mod"
],
"largest_source_bytes": 134501,
"source_files_sampled": 480,
"oversized_source_files": 4,
"agent_instruction_files": [
"AGENTS.md",
"CLAUDE.md"
],
"agent_instruction_max_bytes": 8569
},
"dependencies": {
"manifests": [
"go.mod",
"website/package.json"
],
"advisories": {
"error": null,
"scope": null,
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"go",
"npm"
],
"dependencies": [
{
"name": "charm.land/bubbles/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.1.0"
},
{
"name": "charm.land/bubbletea/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.7"
},
{
"name": "charm.land/glamour/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.0"
},
{
"name": "charm.land/huh/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.3"
},
{
"name": "charm.land/lipgloss/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.3"
},
{
"name": "github.com/charmbracelet/x/ansi",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.11.7"
},
{
"name": "github.com/charmbracelet/x/cellbuf",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.15"
},
{
"name": "github.com/mattn/go-sqlite3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.14.33"
},
{
"name": "github.com/sahilm/fuzzy",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.1.1"
},
{
"name": "github.com/spf13/cobra",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.10.2"
},
{
"name": "github.com/spf13/pflag",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.10"
},
{
"name": "golang.org/x/crypto",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.47.0"
},
{
"name": "golang.org/x/sync",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.20.0"
},
{
"name": "golang.org/x/sys",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.45.0"
},
{
"name": "golang.org/x/term",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.39.0"
},
{
"name": "modernc.org/sqlite",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.41.0"
},
{
"name": "@docusaurus/core",
"manifest": "website/package.json",
"ecosystem": "npm",
"version_constraint": "3.9.2"
},
{
"name": "@docusaurus/preset-classic",
"manifest": "website/package.json",
"ecosystem": "npm",
"version_constraint": "3.9.2"
},
{
"name": "@mdx-js/react",
"manifest": "website/package.json",
"ecosystem": "npm",
"version_constraint": "^3.0.0"
},
{
"name": "clsx",
"manifest": "website/package.json",
"ecosystem": "npm",
"version_constraint": "^2.0.0"
},
{
"name": "lucide-react",
"manifest": "website/package.json",
"ecosystem": "npm",
"version_constraint": "^0.563.0"
},
{
"name": "prism-react-renderer",
"manifest": "website/package.json",
"ecosystem": "npm",
"version_constraint": "^2.3.0"
},
{
"name": "react",
"manifest": "website/package.json",
"ecosystem": "npm",
"version_constraint": "^19.0.0"
},
{
"name": "react-dom",
"manifest": "website/package.json",
"ecosystem": "npm",
"version_constraint": "^19.0.0"
}
],
"all_dependencies": {
"error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"source": null,
"packages": [],
"collected": false,
"truncated": false,
"total_count": null,
"direct_count": null,
"indirect_count": null
}
},
"maintainership": {
"issues": {
"open_prs": 123,
"merged_prs": 33,
"open_issues": 23,
"closed_ratio": 0.324,
"closed_issues": 11,
"closed_unmerged_prs": 11
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "marcus",
"commits": 787,
"avatar_url": "https://avatars.githubusercontent.com/u/3090?v=4"
},
{
"type": "User",
"login": "yashas-salankimatt",
"commits": 19,
"avatar_url": "https://avatars.githubusercontent.com/u/54542393?v=4"
},
{
"type": "User",
"login": "claude",
"commits": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/81847?v=4"
},
{
"type": "User",
"login": "viktorius007",
"commits": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/38939817?v=4"
},
{
"type": "User",
"login": "boozedog",
"commits": 1,
"avatar_url": "https://avatars.githubusercontent.com/u/1410808?v=4"
},
{
"type": "User",
"login": "FredLackeyOfficial",
"commits": 1,
"avatar_url": "https://avatars.githubusercontent.com/u/6161622?v=4"
},
{
"type": "User",
"login": "ricktraveler",
"commits": 1,
"avatar_url": "https://avatars.githubusercontent.com/u/34584238?v=4"
},
{
"type": "User",
"login": "alpjor",
"commits": 1,
"avatar_url": "https://avatars.githubusercontent.com/u/61747?v=4"
},
{
"type": "User",
"login": "rjshrjndrn",
"commits": 1,
"avatar_url": "https://avatars.githubusercontent.com/u/2563385?v=4"
}
],
"contributors_sampled": 9,
"top_contributor_share": 0.966
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"deploy-docs.yml",
"release.yml",
"test-docs.yml"
],
"has_docs_dir": true,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"go.sum",
"package-lock.json"
],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": null,
"reason": "no pull request found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 0,
"reason": "Found 0/30 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 3,
"reason": "project has 1 contributing companies or organizations -- score normalized to 3",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 0,
"reason": "no update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 10,
"reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": 10,
"reason": "packaging workflow detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 2,
"reason": "dependency not pinned by hash detected -- score normalized to 2",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "no SAST tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 0,
"reason": "security policy file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": 0,
"reason": "Project has not signed or included provenance with any releases.",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 0,
"reason": "67 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "b739b10255e71f39ef7490ef0177e556db5b285c",
"ran_at": "2026-07-24T16:29:48Z",
"aggregate_score": 3.3,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": false,
"has_dependabot_config": false
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": null,
"oldest_open_prs": [
{
"number": 61,
"created_at": "2026-03-20T09:57:53Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 62,
"created_at": "2026-03-20T10:06:01Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 63,
"created_at": "2026-03-20T10:13:40Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 66,
"created_at": "2026-03-21T09:49:28Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 67,
"created_at": "2026-03-21T10:01:31Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 71,
"created_at": "2026-03-22T10:30:32Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 72,
"created_at": "2026-03-22T10:40:57Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 73,
"created_at": "2026-03-22T10:51:56Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 74,
"created_at": "2026-03-23T09:43:01Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 75,
"created_at": "2026-03-23T09:52:03Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 76,
"created_at": "2026-03-24T10:45:21Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 77,
"created_at": "2026-03-25T09:32:08Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 78,
"created_at": "2026-03-25T09:41:04Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 79,
"created_at": "2026-03-26T07:52:11Z",
"last_comment_at": "2026-03-26T09:13:19Z",
"last_comment_author": "marcus"
},
{
"number": 80,
"created_at": "2026-03-26T10:16:21Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 81,
"created_at": "2026-03-26T10:26:19Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 82,
"created_at": "2026-03-27T10:24:53Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 83,
"created_at": "2026-03-27T10:32:59Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 84,
"created_at": "2026-03-29T09:39:27Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 86,
"created_at": "2026-03-29T09:56:53Z",
"last_comment_at": null,
"last_comment_author": null
}
],
"last_merged_pr_at": "2026-03-31T02:47:30Z",
"ci_last_conclusion": null,
"oldest_open_issues": [
{
"number": 22,
"created_at": "2026-02-10T17:59:19Z",
"last_comment_at": "2026-02-10T20:44:40Z",
"last_comment_author": "marcus"
},
{
"number": 24,
"created_at": "2026-02-11T13:07:32Z",
"last_comment_at": "2026-02-11T13:09:16Z",
"last_comment_author": "rjshrjndrn"
},
{
"number": 28,
"created_at": "2026-02-12T21:56:32Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 31,
"created_at": "2026-02-15T21:59:37Z",
"last_comment_at": "2026-03-01T19:28:17Z",
"last_comment_author": "marcus"
},
{
"number": 32,
"created_at": "2026-02-15T22:00:38Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 33,
"created_at": "2026-02-16T16:09:29Z",
"last_comment_at": "2026-02-19T17:28:55Z",
"last_comment_author": "marcus"
},
{
"number": 36,
"created_at": "2026-02-17T18:05:58Z",
"last_comment_at": "2026-02-17T18:28:06Z",
"last_comment_author": "marcus"
},
{
"number": 37,
"created_at": "2026-02-17T19:35:49Z",
"last_comment_at": "2026-02-17T19:44:18Z",
"last_comment_author": "Razkaroth"
},
{
"number": 39,
"created_at": "2026-02-17T23:35:28Z",
"last_comment_at": "2026-02-20T04:20:45Z",
"last_comment_author": "marcus"
},
{
"number": 41,
"created_at": "2026-02-19T16:44:49Z",
"last_comment_at": "2026-03-09T23:29:22Z",
"last_comment_author": "marcus"
},
{
"number": 48,
"created_at": "2026-02-24T04:04:48Z",
"last_comment_at": "2026-04-12T22:56:53Z",
"last_comment_author": "justin13888"
},
{
"number": 51,
"created_at": "2026-02-27T19:54:51Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 56,
"created_at": "2026-03-09T20:47:30Z",
"last_comment_at": "2026-05-11T19:37:25Z",
"last_comment_author": "karmajunkie"
},
{
"number": 57,
"created_at": "2026-03-09T22:47:57Z",
"last_comment_at": "2026-03-09T23:29:24Z",
"last_comment_author": "marcus"
},
{
"number": 58,
"created_at": "2026-03-11T15:16:42Z",
"last_comment_at": "2026-03-11T15:28:54Z",
"last_comment_author": "marcus"
},
{
"number": 59,
"created_at": "2026-03-13T22:38:05Z",
"last_comment_at": "2026-03-13T22:59:43Z",
"last_comment_author": "marcus"
},
{
"number": 60,
"created_at": "2026-03-15T07:31:52Z",
"last_comment_at": "2026-03-15T08:57:53Z",
"last_comment_author": "marcus"
},
{
"number": 94,
"created_at": "2026-03-31T18:55:39Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 184,
"created_at": "2026-05-11T09:40:57Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 198,
"created_at": "2026-06-01T08:07:53Z",
"last_comment_at": "2026-06-18T13:18:37Z",
"last_comment_author": "hyperverse"
}
]
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/marcus/td",
"host": "github.com",
"name": "td",
"owner": "marcus"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 60,
"inputs": {
"security": 33,
"vitality": 83,
"community": 50,
"governance": 54,
"engineering": 70
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 83,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "good",
"name": "Development activity",
"note": null,
"notes": [],
"value": 79,
"inputs": {
"commits_last_year": 841,
"human_commit_share": 1,
"days_since_last_push": 5,
"active_weeks_last_year": 22
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 5 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 5
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "22/52 weeks with commits",
"points": 15.2,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 22
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "841 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 841
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": null,
"notes": [],
"value": 90,
"inputs": {
"releases_count": 64,
"latest_release_tag": "v0.51.2",
"releases_from_tags": false,
"days_since_latest_release": 6,
"mean_days_between_releases": 3.4
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "64 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 64
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 6 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 6
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~3.4 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 3.4
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "maintained",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": null,
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": 5,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "last human commit 5 days ago",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_maintained",
"params": {
"days": 5
}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "moderate",
"name": "Community & Adoption",
"value": 50,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "moderate",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"forks": 27,
"stars": 232,
"watchers": 2,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "232 stars",
"points": 38.3,
"status": "partial",
"details": [
{
"code": "stars",
"params": {
"count": 232
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "27 forks",
"points": 11.8,
"status": "partial",
"details": [
{
"code": "forks",
"params": {
"count": 27
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "2 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 2
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "moderate",
"name": "Community health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "moderate",
"name": "Sustainability & Governance",
"value": 54,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 25,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 9,
"top_contributor_share": 0.966
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 97% of commits",
"points": 0.8,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 97
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "9 contributors",
"points": 12.2,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 9
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 1 contributing companies or organizations -- score normalized to 3",
"points": 3,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "at_risk",
"name": "Issue & PR responsiveness",
"note": null,
"notes": [],
"value": 44,
"inputs": {
"merged_prs": 33,
"open_issues": 23,
"closed_issues": 11,
"issue_closed_ratio": 0.324,
"closed_unmerged_prs": 11
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "32% of issues closed",
"points": 15.1,
"status": "partial",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 32
}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "33/44 decided PRs merged",
"points": 28.7,
"status": "partial",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 33,
"decided": 44
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "moderate",
"name": "Ownership & stewardship",
"note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"verified_domain"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 62,
"inputs": {
"followers": 217,
"owner_type": "User",
"is_verified": null,
"owner_login": "marcus",
"public_repos": 28,
"account_age_days": 6706
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "personal (user) account",
"points": 10,
"status": "partial",
"details": [
{
"code": "owner_personal",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": "not applicable to user accounts",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_applicable_to_user_accounts",
"params": {}
}
],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "217 followers of marcus",
"points": 16.8,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 217,
"login": "marcus"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "28 public repos, account ~18 yr old",
"points": 22.6,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 28
}
},
{
"code": "account_age_years",
"params": {
"years": 18
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"github.com/marcus/td"
],
"ecosystems": "go",
"any_deprecated": false,
"min_days_since_publish": 6
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "1 package(s) on go",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 1,
"ecosystems": "go"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 6 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 6
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "99 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 99
}
}
],
"max_points": 20
},
{
"key": "not_deprecated",
"name": "Not deprecated",
"detail": "active, not deprecated or yanked",
"points": 20,
"status": "met",
"details": [
{
"code": "package_not_deprecated",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "good",
"name": "Engineering Quality",
"value": 70,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 60,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "3 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 3
}
}
],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "excellent",
"name": "Documentation",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"topics": [
"agents",
"ai"
],
"has_wiki": true,
"homepage": null,
"has_readme": true,
"has_docs_dir": true,
"has_description": true
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 30,
"status": "met",
"details": [],
"max_points": 30
},
{
"key": "documentation_directory",
"name": "Documentation directory",
"detail": null,
"points": 25,
"status": "met",
"details": [],
"max_points": 25
},
{
"key": "documentation_homepage_site",
"name": "Documentation / homepage site",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": "2 topics",
"points": 10,
"status": "met",
"details": [
{
"code": "topics_count",
"params": {
"count": 2
}
}
],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "at_risk",
"name": "Security",
"value": 33,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "at_risk",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 33,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 17,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 1,
"scorecard_aggregate": 3.3
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 1 contributing companies or organizations -- score normalized to 3",
"points": 0.8,
"status": "partial",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "no update tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 2",
"points": 1,
"status": "partial",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "no SAST tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "67 existing vulnerabilities detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "high_risk_jurisdiction_exposure",
"band": "excellent",
"name": "High-Risk Jurisdiction Exposure",
"note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
"notes": [
{
"code": "jurisdiction_evidence_limits",
"params": {}
}
],
"value": 100,
"inputs": {
"meaning": "self-published location evidence; not nationality or citizenship",
"red_flag": false,
"exposures": [],
"policy_countries": [
"Russia",
"Iran",
"North Korea"
],
"review_only_matches": 0,
"assessed_self_published_locations": 5
},
"components": [
{
"key": "policy_exposure_multiplier",
"name": "Policy exposure multiplier",
"detail": "no confirmed policy-scope location match",
"points": 100,
"status": "met",
"details": [
{
"code": "jurisdiction_no_match",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "good",
"name": "AI Readiness",
"value": 82,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "excellent",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.97,
"agent_instruction_files": [
"AGENTS.md",
"CLAUDE.md"
],
"agent_instruction_max_bytes": 8569
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "AGENTS.md, CLAUDE.md",
"points": 45,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "AGENTS.md, CLAUDE.md"
}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "97 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 97,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "good",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 73,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"go.sum",
"package-lock.json"
],
"has_dockerfile": true,
"typed_language": true,
"bootstrap_files": [
"Makefile"
],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [],
"agent_commit_share": 0.73,
"toolchain_manifests": [
"go.mod"
],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": "Makefile",
"points": 18,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Makefile"
}
}
],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": "Go (statically typed)",
"points": 11,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "Go"
}
}
],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "Dockerfile, lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Dockerfile, lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "73 of the last 100 commits agent-authored or agent-credited",
"points": 10,
"status": "met",
"details": [
{
"code": "agent_authored_commits",
"params": {
"count": 73,
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "no automated dependency updates observed",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_dependency_automation",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 2",
"points": 2,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"primary_language": "Go",
"largest_source_bytes": 134501,
"source_files_sampled": 480,
"oversized_source_files": 4
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Go (statically typed)",
"points": 45,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "Go"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "4/480 source files over 60KB",
"points": 54.5,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 480,
"oversized": 4
}
}
],
"max_points": 55
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
],
"report_type": "repository",
"generated_at": "2026-07-24T16:29:59.861439Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/m/marcus/td.svg",
"full_name": "marcus/td",
"license_state": "standard",
"license_spdx": "MIT"
}