原始 JSON 报告 机器可读
{
"data": {
"repo": {
"topics": [
"ai-agents",
"ast",
"code-generation",
"mcp",
"refactoring",
"rust",
"tree-sitter"
],
"is_fork": false,
"size_kb": 1034,
"has_wiki": false,
"homepage": null,
"languages": {
"Go": 1241163,
"Ruby": 2018,
"Shell": 248,
"Makefile": 607
},
"pushed_at": "2026-07-24T23:53:27Z",
"created_at": "2026-04-05T09:29:38Z",
"owner_type": "User",
"updated_at": "2026-07-18T21:35:21Z",
"description": "Sawmill — MCP server for AST-level multi-language code transformations",
"is_archived": false,
"is_disabled": false,
"license_spdx": "Apache-2.0",
"default_branch": "master",
"license_spdx_raw": "Apache-2.0",
"primary_language": "Go",
"significant_languages": [
"Go"
]
},
"owner": {
"blog": null,
"name": "Marcelo Cantos",
"type": "User",
"login": "marcelocantos",
"company": null,
"location": "Melbourne, Australia",
"followers": 28,
"avatar_url": "https://avatars.githubusercontent.com/u/215143?v=4",
"created_at": "2010-03-03T23:55:32Z",
"is_verified": null,
"public_repos": 64,
"account_age_days": 5988
},
"license": {
"state": "standard",
"spdx_id": "Apache-2.0",
"raw_spdx": "Apache-2.0",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v0.17.0",
"kind": "minor",
"published_at": "2026-07-18T21:35:31Z"
},
{
"tag": "v0.16.0",
"kind": "minor",
"published_at": "2026-07-04T14:18:04Z"
},
{
"tag": "v0.15.0",
"kind": "minor",
"published_at": "2026-06-27T22:33:05Z"
},
{
"tag": "v0.14.0",
"kind": "minor",
"published_at": "2026-05-09T14:05:55Z"
},
{
"tag": "v0.13.0",
"kind": "minor",
"published_at": "2026-05-09T00:56:35Z"
},
{
"tag": "v0.12.0",
"kind": "minor",
"published_at": "2026-04-27T05:21:15Z"
},
{
"tag": "v0.11.0",
"kind": "minor",
"published_at": "2026-04-26T12:22:12Z"
},
{
"tag": "v0.10.0",
"kind": "minor",
"published_at": "2026-04-22T10:17:15Z"
},
{
"tag": "v0.9.0",
"kind": "minor",
"published_at": "2026-04-08T10:19:13Z"
},
{
"tag": "v0.8.0",
"kind": "minor",
"published_at": "2026-04-07T05:14:10Z"
},
{
"tag": "v0.7.0",
"kind": "minor",
"published_at": "2026-04-06T16:23:32Z"
},
{
"tag": "v0.6.0",
"kind": "minor",
"published_at": "2026-04-06T12:51:17Z"
},
{
"tag": "v0.5.0",
"kind": "minor",
"published_at": "2026-04-06T05:45:47Z"
},
{
"tag": "v0.4.0",
"kind": "minor",
"published_at": "2026-04-06T02:25:44Z"
},
{
"tag": "v0.3.0",
"kind": "minor",
"published_at": "2026-04-05T23:38:44Z"
},
{
"tag": "v0.2.0",
"kind": "minor",
"published_at": "2026-04-05T23:18:41Z"
},
{
"tag": "v0.1.0",
"kind": "minor",
"published_at": "2026-04-05T10:21:04Z"
}
],
"recent_commits": [
{
"oid": "c7a3bef7642ea440c3b1b1e444b329d22e2f1a53",
"body": "…tices (#36)\n\n* 🎯T52: Full Java and C# language support\n\nAdd JavaAdapter and CSharpAdapter implementing the complete\nLanguageAdapter interface — definition/identifier/call/type/import/\nfield/method/decorator queries, plus TypeUseQuery and\nStructLiteralQuery, verified against real parsed samples. Jav\n[…]\nE.md.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_017zUNo6ktsEQAzraxriyG2e\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Eight new language adapters, 13-language smoke matrix, attribution no…",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-07-18T21:35:16Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "0b02c94d4b179af11a01ae04973b991aa0c9176c",
"body": "Fable-5 audit remediation: apply/undo/rename/pattern/concurrency fixes (T41-T49)\n\nVerify-first remediation of the Fable-5 finder-stage findings F1-F9\n(targets T41-T49). Each fix has a regression test that was confirmed to\nfail on the unfixed code (via bug-reintroduction mutation) and pass on the\nfix\n[…]\nthis runs in a linked git worktree (go-git can't resolve\nHEAD through the .git gitdir pointer); they pass on a normal checkout/CI.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fable-5 audit remediation: 9 apply/undo/DSL/race fixes (T41–T49) (#35)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-07-06T07:49:43Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "1490d7843e88b6c6f1a2e9aa832a40d7757f0ec8",
"body": "docs: README covers the discovery tier + find_by_concept\n\nRefresh the README ahead of v0.16.0: add a \"Code discovery\" feature\nbullet and list the new discovery tools (search_code, semantic_search,\nfind_by_concept + concept dictionary, graph_expand, central_symbols,\nindex_status) in the MCP tools table. Tool count 57 → 66.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "README: document the discovery tier + find_by_concept (#34)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-07-04T14:17:45Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "5e8c175c38378fa5ddca305ea850395dec9431b7",
"body": "find_by_concept: AST-anchored concept search (reworked onto discovery tier)\n\nConcept-level code search that collapses multi-round grep walks into a\nsingle tool call. Expands a free-text query through stored + built-in\nconcept dictionaries into an alias set, then ranks symbols by alias hits\nacross na\n[…]\n / semantic_search, noting the whole-body-vs-name/sig/doc\n distinction. CLAUDE.md tool count refreshed to 66.\n\nCloses 🎯T35, 🎯T36.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add find_by_concept: AST-anchored concept search (#27)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-07-04T14:02:27Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "379066ce956b24767ad469c1e9779a0201250bc4",
"body": "… (#33)\n\n* Update bullseye.yaml\n\n* Fable-5 deep audit: sawmill findings + targets\n\nFinder-stage candidate findings from an authorized reliability review\n(0 of 18 adversarially verified before an API limit interrupted the run).\nReport in docs/audit/fable-2026-07.md; critical + high findings filed as\n\n[…]\not. Report now annotates\neach finding with its verdict. No targets retired.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fable-5 deep audit: sawmill (2 critical, 8 high) — findings + targets…",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-07-03T06:59:08Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "35066c25831f7857f840e06ae36c6d3baa3c7038",
"body": "* Update bullseye.yaml\n\n* 🎯T40: claudia-driven summaries + typed knowledge graph\n\nAdds an opt-in background summariser that drives github.com/marcelocantos/\nclaudia in Task mode to produce per-symbol one-line summaries plus typed\nknowledge-graph edges (reads / writes / calls / throws / returns).\n\nEn\n[…]\n2).\n\nThe user must opt in — by default no LLM is called on Sawmill startup.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 <noreply@anthropic.com>",
"is_bot": false,
"headline": "🎯T40: claudia-driven summaries + LLM knowledge graph (#32)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-06-29T15:24:38Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a504a5676eb7352568baf3790e3ebb5d34bfe548",
"body": "…arch (#31)\n\n* Update bullseye.yaml\n\n* 🎯T39: hybrid lexical/vector/graph retrieval\n\nAdds a semantic_search MCP tool that fuses three signals over the\ndiscovery index via reciprocal-rank-fusion:\n\n - BM25 from the FTS5 search_code path (always on)\n - vec cosine over an in-memory vector index (ac\n[…]\ne golden queries.\n - Both agents-guide.md copies document semantic_search.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 <noreply@anthropic.com>",
"is_bot": false,
"headline": "🎯T39: Hybrid retrieval — vector embeddings + RRF fusion + semantic_se…",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-06-29T11:32:10Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "fe3a60b86c4b8ee7481af0052086d091f2a1c80a",
"body": "* Update bullseye.yaml\n\n* 🎯T38.1: FTS5 symbol search via search_code MCP tool\n\nAdd a symbols_fts FTS5 virtual table covering the symbol name, the first\nline of its declaration (signature), and any leading line-comment block.\nWired into UpdateSymbols so the FTS rows stay aligned with symbols.id\nacros\n[…]\nols) in both the root and embedded agents-guide.md.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>\n\n* Update bullseye.yaml\n\n---------\n\nCo-authored-by: Claude Opus 4.7 <noreply@anthropic.com>",
"is_bot": false,
"headline": "🎯T38: Discovery tier — FTS5 search, reference graph, PageRank (#30)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-06-29T06:46:29Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "7b34e6bfe34a7080af219bd91cd395c86d58a495",
"body": "* 🎯T37: skip oversized and minified files before tree-sitter\n\nPID 7500 (sawmill serve, started 7 Jun) was pegged at 99.5% CPU with\n24.5h accumulated CPU time, stuck in odvcencio/gotreesitter's\nretryFullParseWithDFA → mergeStacksWithScratch on bundle output under a\nSvelteKit wwwroot. Tree-sitter's GL\n[…]\n Claude Opus 4.7 <noreply@anthropic.com>\n\n* 🎯T37: record target as achieved\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 <noreply@anthropic.com>",
"is_bot": false,
"headline": "🎯T37: Skip oversized and minified files before tree-sitter (#29)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-06-27T22:32:40Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "43d273b984dbf0d45ece462b5b4fe58931ba85f7",
"body": "ci: bump GitHub Actions to Node-24 majors\n\nPins checkout@v6, setup-go@v6, setup-node@v6, cache@v5, setup-java@v5,\nsetup-python@v6, upload-artifact@v7, download-artifact@v8 to clear the\nNode-20 runtime deprecation (GitHub force-migrates on 2026-06-16).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "ci: bump GitHub Actions to Node 24 majors (#28)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-06-20T21:58:01Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "ff41b6dab1f362acf6346d3427d83bdc40c58bb4",
"body": "* Update bullseye.yaml\n\n* Fix scope.New blocking on recursive gitignore walk\n\nThe first cut of scope.New used go-git's gitignore.ReadPatterns,\nwhich recursively descends the entire tree to collect every nested\n.gitignore. On a Unity-sized project (5,800+ files, thousands of\ndirectories under Assets/\n[…]\ntest that builds a 1000-dir tree with a\n.gitignore at every leaf and asserts scope.New completes in under\n500ms (the recursive variant ran in seconds; on a real Unity tree\nit ran for tens of minutes).",
"is_bot": false,
"headline": "Fix scope.New blocking on recursive gitignore walk (#26)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-05-09T14:05:30Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cc07879fdc8f8d20d42af2ea1fa1ea32287e8fc5",
"body": "Update STABILITY.md snapshot (v0.12.0 → v0.13.0, +1 surface item for\nfind_references.include_libraries) and add a new gap entry for the\nscope classifier. Add an \"Indexing scopes\" gotcha to both the root\nagents-guide.md and the embedded copy at go/mcp/agents-guide.md so\nagents understand owned/library/ignored behaviour and the\nfind_references default-to-owned filter.",
"is_bot": false,
"headline": "Release prep v0.13.0: scope classification + STABILITY refresh (#25)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-05-09T00:56:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9de8f17fb3afbcf2490420008448acddc3fb54a6",
"body": "…(#24)\n\n* bullseye: use ✅/❌ emoji in Makefile output\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>\n\n* Update bullseye.yaml\n\n* Introduce three-tier scope classification (owned/library/ignored) for indexing\n\nA Unity project store grew to 6.3 GB because the walker descended into\n[…]\ninclude_libraries flag (default false) and is filtered to owned scope by\ndefault via FindSymbolsInScopes.\n\nCloses 🎯T34.\n\n---------\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Three-tier scope classification (owned/library/ignored) for indexing …",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-05-09T00:43:46Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "33a756617d0910efb15e19873d96e9baeab07c96",
"body": "Rewrites the `Commit: pending` placeholder in docs/audit-log.md left\nby the release-prep PR to the real squash-merge SHA `a47d804`.\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: record v0.12.0 release-prep merge commit hash (#22) (#23)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-27T05:15:35Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "a47d804aa9fb65d15765bb9fda0260c16464be6e",
"body": "…_way + homebrew deps (#22)\n\n* merge: AST-aware three-way merge engine (🎯T29)\n\nNew go/merge package providing Merge(base, ours, theirs, adapter, opts)\nthat resolves edits which don't overlap structurally — parallel method\nadditions, parallel imports, format-vs-logic, identical adds, etc. —\nwithout f\n[…]\n PR will rewrite to the real merge-commit SHA.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Release v0.12.0: AST-aware merge + git mergetool/driver + merge_three…",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-27T05:05:09Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "5626acd74f091550a015fe7b92f1c4595515e847",
"body": "Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: record v0.11.0 release-prep merge commit hash (#21)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-26T12:16:57Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "a462f4a4de04792c8e36b7148a4282894a3efcea",
"body": "…efresh (#20)\n\n* bullseye: add 🎯T28 — heartbeat pings for streamable-HTTP MCP server\n\nMirrors the mnemo fix (master 4057332): mark3labs/mcp-go's\nStreamableHTTPServer disables WithHeartbeatInterval by default, so\nidle SSE streams collapse after ~3 minutes and the next tool call\nsurfaces as 'MCP error\n[…]\n append /release v0.11.0 entry (Commit: pending).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Release prep v0.11.0: heartbeat fix + STABILITY/README/agents-guide r…",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-26T12:01:20Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "5a00a653c2ccd61c9b22a4ddabc239610c47dd69",
"body": "PR #18 landed apply_multi_root_pr, satisfying 🎯T27's PR-lifecycle\nacceptance. With 🎯T25 (multi-repo fan-out, achieved earlier) plus\n🎯T27, all four of 🎯T5's acceptance criteria are met:\n- multi-root operations ✓\n- daemon multi-repo concurrency ✓ (already true)\n- per-repo diffs/previews ✓\n- PR lifecycle ✓\n\nRetiring T5 closes out the multi-repo arc.\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "bullseye: retire 🎯T27 + 🎯T5 — multi-repo arc complete (#19)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-25T16:01:02Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "453815ebb5ee55d280401d7de7257ff8d7af8447",
"body": "Adds the apply_multi_root_pr MCP tool that turns per-repo diffs from\ntransform_multi_root into per-repo PRs (branch + commit + push + gh pr\ncreate). Mirrors T25's error-isolation pattern: per-repo failures are\ncaptured in RootPRBundle.Error without aborting siblings.\n\n- Input: flat list of {root, di\n[…]\nion, branch reuse,\n templating, bad-root, and full handler integration\n- Demo: docs/demos/multi-repo-pr.md mirroring multi-repo-transform.md\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "mcp: add apply_multi_root_pr tool (🎯T27) (#18)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-25T15:48:39Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e77c95d04b4060e864c59b611df4e77a2c8657be",
"body": "🎯T25 retirement left 🎯T5 unblocked but with no observable\ncheckpoint downstream. T27 carves out the remaining substantive\nslice: take transform_multi_root's per-repo diffs and turn them\ninto per-repo PRs (branch + commit + push + open PR), with the\nsame per-repo error isolation pattern.\n\nTogether T25 + T27 cover T5's user-facing value (multi-repo fan-out\n+ PR delivery); the daemon-concurrency acceptance was already true.\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "bullseye: add 🎯T27 — multi-repo PR lifecycle observable for 🎯T5 (#17)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-25T14:42:13Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8f72529d465984ba93d5e54264656b3218fca9c9",
"body": "Set aside 🎯T7 (cross-representation semantic identity) and its\nobservable 🎯T26 (embedded-DSL via tree-sitter injection) following\na viability assessment of the canonical SQL-in-Go case.\n\nThe bounded slice (single literal, no concatenation, parse-only) is\ntoo narrow to anchor T7's vision. The meaning\n[…]\nd\ncross-references) or if the upstream tree-sitter ecosystem makes\ninline injection cheap. Full rationale recorded on the targets.\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "bullseye: park 🎯T7 + 🎯T26 — cross-representation identity deferred (#16)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-25T13:46:50Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "dc430568b74a8f6b5273fda4cbf2e40cf04b36c9",
"body": "…N repos (#15)\n\n* bullseye: retire 🎯T8, add observables 🎯T25/🎯T26\n\nRetire 🎯T8 (cross-representation transforms) — its 3 sub-targets are\nall achieved, and remaining acceptance items can be respawned as\nfresh targets when pursued.\n\nAdd observable checkpoints 🎯T25 (multi-repo coordinated transform\ndemo\n[…]\nT5 to pick up its remaining scope (PR lifecycle).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "bullseye: retire 🎯T8 + 🎯T25, add 🎯T26 observable, generalise 🎯T25 to …",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-25T10:51:05Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "89b67f79598f842ccbe3cc857cd39df3782b462b",
"body": "…isolation (#14)\n\nAdd TestTransformMultiRootThreeRoots — exercises N=3 (two good roots with\none having two files, one non-existent root) and asserts:\n- all three roots appear in the result map\n- per-root file counts and diff counts are correct\n- the bad root records a non-empty Error field without a\n[…]\nntentionally failing root), the\nexpected JSON output shape, the runnable Go test invocation, and a\nshell curl script for manual HTTP testing.\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "🎯T25: prove transform_multi_root end-to-end with N>2 roots and error …",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-25T10:25:58Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "4cc09538ca1db5bd61718cb36469db29534474b8",
"body": "* swap tree-sitter runtime: go-tree-sitter (CGo) → gotreesitter (pure Go)\n\nReplace github.com/tree-sitter/go-tree-sitter and the five per-language\nCGo grammar packages with github.com/odvcencio/gotreesitter, a pure-Go\ntree-sitter runtime with grammars compiled to Go data tables (ts2go blobs).\n\nIntro\n[…]\nGraphQLGrammar: parses a query operation, asserts \"document\" root child\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "🎯T7.0: swap tree-sitter runtime to pure-Go gotreesitter (#13)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-25T05:31:33Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a0b9b0be61248be10bed5d100d7c6d65c337d4da",
"body": "Adds a new MCP tool that applies an ordered list of transforms across N\nproject roots in a single call. Each root is loaded or reused via the\nsession's ModelLoader (pool-backed in production), producing per-root\nRootDiffBundle results keyed by absolute path. The session's pending\nstate is intentionally untouched so single-root apply/undo is isolated.\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "mcp: add transform_multi_root tool (🎯T5.1) (#11)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-25T01:48:37Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "708f9badc1cef55e0806203252be3d71f9182387",
"body": "Replaces the placeholder `Commit: pending` from PR #9 with the actual\nsquash-merge commit hash. Tagging v0.10.0 follows once this lands.",
"is_bot": false,
"headline": "audit-log: back-fill v0.10.0 commit hash (a717113) (#10)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-22T10:16:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a717113f5a4754b1e28707d2bf08196c1ff18114",
"body": "* Update STABILITY.md for v0.10.0 (54 tools, 158 parameters)\n\nAdd 21 new MCP tool rows (git history family, semantic_diff, api_changelog,\ngit_semantic_bisect, equivalence family, fix/auto_fix family, promote_constant,\nextract_to_env, migrate_pattern, learn_from_observation, seed_fixes). Mark\ncheck_c\n[…]\nconfig block + lsof / no-curl guidance.\n- audit-log: append v0.10.0 entry (commit hash will be back-filled in\n the follow-up PR).\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Pre-release docs for v0.10.0 (#9)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-22T10:09:25Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b37f6dcc32b9c2571791ab3bcfed6d1856b08fbb",
"body": "…ework (#8)\n\n* Remove auto-rendered docs/targets.md\n\ntargets.yaml is the canonical source of truth; the rendered markdown view is unused.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n* Move targets.yaml to bullseye.yaml, remove targets.md\n\nCo-Authored-By: Claude Opus 4.6 (1\n[…]\nests) —\neach test runs in under 50ms under -race.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Pillars 🎯T1 + 🎯T3 + 🎯T24; cross-rep transforms 🎯T8.1–T8.3; HTTP MCP r…",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-20T11:57:59Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "37d0986c8a11c6ca63dc10cc17cd02d19f975d8f",
"body": "A thin wrapper around go-git exposing a focused API: Open, Resolve,\nHead, GetCommit, WalkCommits, FilesAtCommit, ReadBlob. Uses TreeWalker\nto avoid hydrating blobs when enumerating files, and walks the\nfirst-parent chain manually since go-git's LogOptions doesn't support\nit natively.\n\nFoundation for 🎯T6 git semantic indexing — all subsequent sub-targets\n(T10-T14) depend on this.\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add gitrepo package for programmatic git object access (🎯T9) (#7)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-11T13:42:48Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "e282ff1f9d1e7929e7b4b2a1fd9514248bb92d91",
"body": "* Store source bytes in SQLite files table\n\nAdd source BLOB column to the files table (with migration for existing\ndatabases). UpsertFile now accepts and stores source bytes alongside\nmetadata. Add ReadSource, FileLanguage, LanguageSummary, and FileCount\nmethods to the Store for future use by the on\n[…]\nepresentation transforms (extract, inline, sync).\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "On-demand CST architecture and new targets (🎯T4, 🎯T6-T8) (#6)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-11T02:05:15Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "05c5854b45bbfc86d253ab64e968baca4db2f5b6",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add audit log entry for v0.9.0 release",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-08T10:19:06Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "172aab05b57b5a63b03eea17c7a79d9925f8bc1e",
"body": "* Update 🎯T21: add observation-based learning and pre-populated catalogue\n\nTwo bootstrapping paths: pre-built entries for common compiler errors,\nand learned entries from watching the agent's own fix behaviour.\nCost 8 → 13 (learning loop is a new subsystem).\n\nCo-Authored-By: Claude Opus 4.6 (1M cont\n[…]\nABILITY.md for v0.9.0: global socket architecture\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Pre-release docs for v0.9.0 (#5)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-08T10:18:20Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "770475fbe8af0ff112c6b5f173548af8093e0259",
"body": "* Refactor to single global daemon with per-project model pool\n\nThe daemon (`sawmill serve`) now listens on a single well-known socket\n(~/.sawmill/sawmill.sock) instead of spawning per-project daemons.\nEach proxy connection announces its project root in the mcpbridge\nhandshake; the daemon lazily loa\n[…]\ncom>\n\n* Sync bullseye targets after 🎯T20 achieved\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Global daemon with active model manager (🎯T20) (#4)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-08T09:46:47Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "29c9579ba36891ea759806e0ae589ff40a12fe96",
"body": "* Update convergence report: T15 achieved, T16 unblocked, recommend T17\n\nT15 (add_field) now achieved with the LSP+tools PR merge. T16 (type\nshape migration) is newly unblocked. T17 (dependency impact analysis)\nis the highest-weight unblocked target at 3.3.\n\nCo-Authored-By: Claude Opus 4.6 (1M conte\n[…]\nic.com>\n\n* Add audit log entry for v0.8.0 release\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add dependency_usage, structural invariants, and migrate_type tools (#3)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-07T05:13:51Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "3feb133a779ea1ddd1fdcbb47de37826371e7cdf",
"body": "* Add implementation designs and targets for LSP-powered features\n\nFlesh out docs/agent-usage-archaeology.md with Part 4: detailed\nimplementation designs for the LSP client (go.lsp.dev libraries),\nfile rename with import cascade, add-field propagation, type shape\nmigration, dependency impact analysi\n[…]\nation, type-not-found, and no-construction-sites.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add LSP client, rename_file, clone_and_adapt, and add_field tools (#2)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T23:17:48Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "3836e85f03903e60c1c2d4991827aa17b58b5672",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add audit log entry for v0.7.0 release",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T16:23:19Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "157b3cc6dd96c4ef4431b6b47f4a5331b89a6d6d",
"body": "* Refactor MCP server to use mcpbridge library\n\nReplace the custom proxy/handshake/daemon protocol with mcpbridge,\nfollowing the pattern established in mnemo. Key changes:\n\n- mcp: Replace SawmillServer with Handler implementing mcpbridge.ToolHandler;\n extract tool definitions into standalone Defini\n[…]\n --socket flag and handshake\nprotocol references.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Release v0.7.0 (#1)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T16:22:46Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "7e838c3cfa28e8a21921375e85d2b0c1fc382929",
"body": "Store and backups now live centrally:\n- ~/.sawmill/stores/<hash>/store.db (was <root>/.sawmill/store.db)\n- ~/.sawmill/backups/<hash>/<rel-path>.bak (was <file>.sawmill.bak)\n\nNo .sawmill/ directory, no .bak files, no .new files in project trees.\nNothing to .gitignore. The paths package computes locations from a\nSHA-256 hash of the project root.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Move all sawmill state to ~/.sawmill/ — zero project footprint",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T14:19:56Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6c8af6d6e6dae94d76e582635c72a8f8ac30687e",
"body": "Explores declaring bidirectional equivalences between code patterns\nwithin a single language — a tractable extraction from a broader\ncross-language transpilation vision originating in the arr.ai project.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add research paper on intra-language pattern equivalences (🎯T12)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T13:56:28Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c7e14eafe8cb29b28960927f22adb4c8bb96f2d0",
"body": "Tree-sitter grammar bindings require CGo. Since each platform builds\non its native runner, CGo works without cross-compilation.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fix release build: remove CGO_ENABLED=0",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T12:51:01Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2fb0acc12505908c098a98076a4d7ef61de7f366",
"body": "- TestDebouncing: tolerate up to 2 events (debouncer may split across\n windows on slow CI); increase drain wait to 300ms\n- CI workflows: add cache-dependency-path for go.sum in go/ subdir\n- Release workflow: add fail-fast: false\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fix flaky debounce test and CI cache path",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T12:48:37Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "69e31d9b802a0539524feb989bb1c1845ad44f23",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add audit log for v0.6.0 release",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T12:45:24Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "4a8d4f8aaf4385e717f84e365137381662f3c4d0",
"body": "The stdio process now sends a SHA-256 hash of its own executable in\nthe handshake. The daemon compares it against its own hash and rejects\nthe connection with a \"restart the service\" message if they differ.\nThis prevents version skew between the proxy and daemon after upgrades.\n\nModelled after mnemo\n[…]\nne (no JSON), it's accepted.\n\nAlso adds STABILITY.md with the full interaction surface catalogue\n(107 items) and 1.0 gap analysis.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add binary hash validation to daemon handshake",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T12:43:34Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "50c91d1bc6aac6e176de76f91fb75930b2eeae0a",
"body": "- Update README for Go rewrite: remove Rust references, document new\n command structure (sawmill / sawmill serve), add quick start prompt,\n update architecture diagram\n- Update agents-guide.md: 4-step installation with brew services,\n updated MCP registration (no subcommand), verification step\n- \n[…]\nh service block\n- Remove goreleaser config (replaced by direct build + upload)\n- Add go/sawmill to .gitignore, remove stale binary\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Prepare for v0.6.0 release",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T12:21:40Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "fdac3c86d6e9932b7fa1c24a29790344d6d74033",
"body": "The daemon pre-loads the model from the project root sent during the\nsocket handshake. MCP tools work immediately without an explicit parse\ncall. parse with no path returns the pre-loaded model's summary;\nparse with a path still loads a new model.\n\nNew E2E test (TestE2EImplicitParse) verifies query works without parse\nwhen connected via the daemon.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Pass working directory through daemon handshake; parse is now optional",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T11:26:43Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "524fe2194dcc4466cdddbfb7e5fbf8edf41c858e",
"body": "Three tests exercising the production architecture:\n\n- TestE2EParseQueryRenameApplyUndo — full workflow: connect to daemon\n socket, MCP initialize, parse, query, rename, apply (verify file on\n disk), undo (verify restored)\n- TestE2ETransformApply — transform remove via daemon, verify file\n- TestE2EMultipleSessionsSameProject �� two concurrent MCP sessions\n against the same project root via shared daemon\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add E2E tests for the full daemon→MCP→disk path",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T11:19:38Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "3d16e98f97285d42db68cb135b664b1a5fe9fb69",
"body": "- `sawmill` (no args) is the MCP stdio server for clients to launch\n- `sawmill serve` starts the background daemon (for brew services)\n- Auto-start: `sawmill` spawns `sawmill serve` if daemon isn't running\n- Updated Homebrew formula and launchd plist to use `sawmill serve`\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Rename commands: sawmill (stdio MCP) and sawmill serve (daemon)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T11:16:35Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "0161af277c39e836c314f49ce4ca8ca60e3c0fcb",
"body": "sawmill serve now auto-starts the daemon if it isn't running, waits\nfor it to become ready (up to 3s), then proxies. No more in-process\nfallback or warning messages. The daemon is an implementation detail\nthat clients never interact with directly.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Auto-start daemon from serve — no fallback mode",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T11:14:32Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "679f31e55ba5a8abe7f2ecae1823d3ba68f291fa",
"body": "Delete all Rust source (src/, Cargo.toml, Cargo.lock), Rust CI\n(ci.yaml), and Rust release workflow (release.yaml). Update CLAUDE.md\nand .gitignore to reflect the Go project.\n\nThe Go rewrite at go/ has full feature parity: 80 tests, 16 packages,\n20 MCP tools, daemon architecture, file watching, brew services, and\ngoreleaser-based release workflow.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Remove Rust codebase — Go rewrite is complete",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T11:07:13Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "09c874d3a588fd923268b579709e5ad187914622",
"body": "Adds .goreleaser.yml (cross-compile for macOS arm64, Linux x86_64/arm64,\nWindows x86_64/arm64 with CGO_ENABLED=0), .github/workflows/release.yml\n(triggered on v* tags, runs tests then goreleaser), and a root Makefile\nwith build/test/release-local targets.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add Go release workflow with goreleaser",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T10:54:20Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "5790ba16f9bf90b0ec9f5720764baadb69db1587",
"body": "27 integration tests covering all MCP tool handlers: parse, rename,\nquery, transform (declarative, JS, batch), apply/undo, codegen,\nrecipes (teach/instantiate/list), conventions (teach/check/list/delete),\nfind_symbol, find_references, get_agent_prompt, add/remove_parameter,\nand edge cases (no matche\n[…]\nble\n to derive the original path. Changed to appendExt which preserves\n the original extension (main.py -> main.py.sawmill.bak).\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add MCP integration tests and fix parameter/undo bugs",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T10:53:17Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "30f065263cb2dd3c293f68d4e156c024d291c239",
"body": "Adds go/watcher package (fsnotify-backed, 100ms debounce, recursive\ndirectory watching, skips hidden and build dirs) and wires it into\nCodebaseModel: Load() starts the watcher, Sync() drains pending events\nand re-parses changed files, Close() shuts it down. Four tests cover\ncreate/modify/remove detection and debouncing.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Port file watcher to Go with fsnotify and debouncing",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T10:45:20Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "5746a53fcfbfa4ff17a58564c4e7c6e0bd01b133",
"body": "The get_agent_prompt tool now uses the embedded guide (always available\nin release binaries) with disk fallback for development.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Embed agents-guide.md in Go binary via go:embed",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T10:42:59Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "76b6d16d4c5b29e6dc80d667297c36feb440e02a",
"body": "- Add go/rewrite/rewrite_test.go: 5 tests porting all Rust rewrite tests\n (identity_round_trip, rename_single_identifier, rename_function,\n rename_preserves_formatting, diff_output)\n- Add .github/workflows/go.yml for Go CI (build + race-detector tests)\n- Total Go tests: 46 (up from 41); all pass\n- Mark 🎯T11.7 and 🎯T11 as achieved in docs/targets.md\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Port rewrite tests to Go, add Go CI workflow (🎯T11.7)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T10:32:48Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "3307e618b146ecdc146e5356000d760ea9db100a",
"body": "- go/proxy/proxy_test.go: TestProxyConnectsAndRelays verifies end-to-end\n relay through a fake echo daemon\n- docs/targets.md: mark 🎯T11.5 achieved; update 🎯T11.4 status\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add stdio proxy test and mark 🎯T11.5 achieved",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T10:28:59Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "81c9cfb3bb8c8ca156a271cf6099e30e54e91a5e",
"body": "- homebrew/sawmill.rb: Homebrew formula with service block for\n `brew services start sawmill`\n- homebrew/io.sawmill.daemon.plist: standalone launchd plist for\n non-Homebrew users\n- go/cmd/sawmill/main.go: switch version to ldflags var; add\n --help-agent flag\n- go/mcp/server.go: add NewServerWithM\n[…]\n into handleConn so daemon\n connections get full MCP JSON-RPC service\n- go/proxy/proxy.go: stdio-to-socket proxy package (🎯T11.5 groundwork)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add brew services support and wire daemon MCP connections (🎯T11.6)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T10:27:03Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "c64fecc53ab4c2f4d9e9b54d1f338179d064d5bc",
"body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Update targets: mark 🎯T11.3 and 🎯T11.4 as achieved",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T10:03:58Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6bc936cef1e938ff3b635bb4c0020571dffd9182",
"body": "Implements the full sawmill MCP server in Go using mark3labs/mcp-go:\n\n- go/mcp/server.go — SawmillServer with mutex-guarded state (model,\n pending changes, last backups), NewServer constructor, Serve(ctx)\n method that registers all tools and serves over stdio, registerTools\n wiring all 20 tools t\n[…]\ng Tree-sitter parameter nodes.\n\n- go/cmd/sawmill/main.go — Added `serve` subcommand that wires up the\n MCP server with signal-aware context.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add Go MCP server package (🎯T11.4)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T10:03:40Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "74b81c0e102df90c198cbf510476a3ab801500ff",
"body": "Implements the sawmill daemon: a Unix socket server that lazily loads and\ncaches a CodebaseModel per project root, responds with a JSON status message,\nand keeps connections open for future MCP protocol use (🎯T11.4). Includes\nfour passing tests covering connect, multi-project caching, shutdown, and\nempty-root error handling. Adds `sawmill daemon` and `sawmill version` CLI\nsubcommands via the standard `flag` package.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add Go daemon infrastructure and CLI entry point (🎯T11.3)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T09:56:39Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b9b42018508178aa8236ec287db429a50e423aff",
"body": "Persistent codebase model with incremental parsing: checks file mtimes\nand content hashes against the SQLite store, only re-parses changed\nfiles. Provides Load (persistent), LoadEphemeral (in-memory for\ntesting), Sync (placeholder for file watching), and delegates for\nrecipe/convention/symbol operations.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add model package — CodebaseModel tying together forest and store",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T09:54:20Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "88dbc44c69b1e4ee48291a66d66011c918a4c2fe",
"body": "Pure Go SQLite store with 7 tests, same schema as Rust.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Mark 🎯T11.2 store port as achieved",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T09:07:09Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "558a6255a8467d9ea6ceb9d9d8e3be6acdb45193",
"body": "SQLite persistence layer using modernc.org/sqlite (pure Go, consistent\nwith the modernc.org/quickjs choice). Same schema as Rust: files,\nsymbols, recipes, conventions tables with WAL mode and foreign keys.\n\nUses database/sql interface with transactions for bulk symbol updates.\n7 new tests covering all CRUD operations, cascade deletes, prefix\nmatching, and symbol replacement.\n\nTotal Go tests: 36 (29 existing + 7 store).\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Port store package to Go (🎯T11.2)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T09:06:52Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "95038b8fd93d87e987fe1eab35cfc8912aff548b",
"body": "Converted T11 sub-targets from bullet points to proper ### headings\nwith Weight, Parent, Depends on, Gates, and Status fields so rank.py\ncan parse and rank them. No functional change to target definitions.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Restructure targets.md for rank.py compatibility",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T09:03:44Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2fba0677d0f2ef5568b66f04e88392ca5bdc71cd",
"body": "All 7 packages ported to Go with 29 passing tests.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Mark 🎯T11.1 core logic port as achieved",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T08:53:36Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "307481996f49c996e57a4f696a6c6981ee4abd2e",
"body": "Complete the 🎯T11.1 core logic port by adding the final two packages:\n\n- jsengine: QuickJS-based per-node JS transform engine (RunJSTransform)\n- codegen: Full codegen runtime with ctx API (RunCodegen,\n RunConventionCheck, ValidateChanges, StructuralChecks)\n\nUses modernc.org/quickjs (pure Go, no CGo\n[…]\n\nstated project goal.\n\n17 new tests (5 jsengine + 12 codegen), all passing. Total Go test\ncount: 29. All 35 Rust tests still pass.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Port codegen and jsengine packages to Go",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T08:53:05Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e202241af61b99b9f382612b30f862137342301e",
"body": "Transform engine: match/act with abstract and raw tree-sitter queries,\n8 action types. 7 tests ported from Rust, all passing.\n\nIndex: symbol extraction (functions, types, imports, calls).\n\nExemplar: teach-by-example template extraction with case-variant\nawareness. 5 tests ported from Rust, all passing.\n\nPart of 🎯T11.1 (core logic port).\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Port transform, index, and exemplar packages to Go",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T07:09:48Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "bb0b14359eea932dfdc436df69112419b92eef0d",
"body": "Port language adapters (Python, Rust, Go, TypeScript, C++), forest\n(parsing, file walking, backup/undo), and rewrite (rename, diff,\nformat, edit application) from Rust to Go.\n\nUses official tree-sitter Go bindings (go-tree-sitter v0.25.0).\nAll packages build cleanly.\n\nPart of 🎯T11.1 (core logic port).\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Begin Go rewrite: adapters, forest, rewrite packages",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T07:02:10Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b81c1dd1b76c49475b3a93cf32c1e65a3449b0d6",
"body": "Rewrite from Rust to Go with daemon architecture — single persistent\nservice managing multiple projects, stdio proxy for MCP clients,\nbrew services integration.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add 🎯T11: Go rewrite + daemon architecture",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T06:21:26Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "82d11c7224027c82c179e13a7886c1cf9f33ea0a",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Bump version to 0.5.0",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T05:45:38Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "36e0e927c896ce21fec9f489e7c3ca5de24c26ff",
"body": "Extract parameter types into mcp/params.rs (339 lines) and helper\nfunctions (batch transforms, parameter editing) into mcp/helpers.rs\n(397 lines). mod.rs retains the server struct, tool implementations,\nand serve() at 1310 lines (down from 2031).\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Split mcp.rs into submodules",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T05:39:53Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "26319d038ec526631573662aae4d132bbbf20cda",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Bump version to 0.4.0",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T02:25:34Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "ba7ed7402ca8e1f048cf3b1bad4cb98ef35a98ba",
"body": "Comprehensive rename: binary name, package name, struct names (CanopyServer →\nSawmillServer), file extensions (.canopy.bak/.new → .sawmill.bak/.new), internal\ndirectory (.canopy/ → .sawmill/), GitHub URLs, Homebrew formula, and all prose\nreferences across source, docs, and config files.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Rename project from canopy to sawmill",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-06T02:20:15Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "519fa60f1f1c28ef3b4f559e5d555c3d126df9bd",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Bump version to 0.3.0",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T23:38:36Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "279fecd4384e2bebb7670b8bf5b4946fb1ab4a27",
"body": "README: restructured Quick Start into Installation with numbered steps.\nHomebrew, cargo install, and from-source paths. Claude Code one-liner\n(claude mcp add --scope user). Explicit agent instructions in the\n\"For AI agents\" section.\n\nagents-guide.md: replaced MCP Server Setup with full Installation\nsection including brew, cargo install, claude mcp add, and session\nrestart note.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add clear installation instructions for agents and users",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T23:37:19Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2cd1485afb77ba3cdf91c50f14c24d98ec19fe05",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add audit log entry for v0.2.0 release",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T23:18:23Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "70570ae9a1d343ef00529987ac0e04e9f0b88138",
"body": "- Cargo.toml version → 0.2.0\n- STABILITY.md: update version, mark Frontiers D/E/K as done,\n add get_agent_prompt to surface catalogue\n- README: add get_agent_prompt to tool table\n- .gitignore: exclude generated convergence-report.md\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Bump version to 0.2.0, update docs for release",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T13:31:36Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "0acaf0d7b6b9340a55145409c5c241a000bafac0",
"body": "- Allow mut_from_ref on LspProxy::get() (intentional interior mutability)\n- Collapse nested if in check_conventions_on_changes\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fix clippy warnings from audit fixes",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T12:36:56Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b24ccb6d50ffed3476bdddc6b73c0adbb302006e",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add TODO for mcp.rs split and HOMEBREW_TAP_TOKEN setup",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T12:36:12Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "7b4667a9f9760722d71af483b5f9cf03f0fafe94",
"body": "Test on both ubuntu-latest and macos-latest to match release targets.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add macOS to CI matrix",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T12:35:20Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "9a39dfa51b6f585b05dee4330f3033b42e02692c",
"body": "Use OsStr byte-level suffix stripping instead of\nto_string_lossy().trim_end_matches() for deriving original paths\nfrom .canopy.bak backups.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fix path manipulation in undo_from_backups",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T12:35:17Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2f3154a543a2a1f132fb77547097be9dc41b8c3a",
"body": "Convention checks were running against the pre-change forest because\nthe `changes` parameter was unused. Now clones the forest and re-parses\nchanged files from their new content before running checks.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fix check_conventions_on_changes to check post-change state",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T12:34:38Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c27f4bc50438640b89a6a3cd703f3745d847e8bf",
"body": "Reduces four scattered `unsafe { &mut *self.ptr }` blocks to one\ncentral `get()` method with a documented safety contract. Also removes\n`unsafe impl Send` — LspProxy is only ever used on the single thread\nrunning QuickJS, so Send was unnecessary and misleading.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Consolidate unsafe in LspProxy behind a single get() method",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T12:34:10Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "d32fb1405a59d7e54b86deae25072296bf430352",
"body": "Replace eprintln! with a suppressed binding to avoid writing to stderr,\nwhich shares the stdio transport used by the MCP JSON-RPC protocol.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fix watcher eprintln! interfering with stdio MCP protocol",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T12:33:50Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "87d4d0c4c8404d78e28ef37f5287c817da44363f",
"body": "The previous implementation created an Instant then immediately checked\nelapsed < timeout, which is always true, making it a plain blocking read\nwith no timeout enforcement. Replace with poll(2) via libc to check fd\nreadability before blocking, giving a real timeout for the diagnostics\npolling loop.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fix broken timeout in LspConnection::try_read_message",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T12:33:21Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "d6b65e33632543e95478974210945ee59fc52376",
"body": "Fix cargo fmt violation and 2 clippy warnings (collapsible if) in\nsrc/mcp.rs that would fail CI. Audit report with 12 findings\n(0 critical, 0 high, 5 medium, 5 low, 2 info) written to\ndocs/audit-2026-04-05.md.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Comprehensive codebase audit: fix fmt/clippy, add report",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T12:27:16Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "83384da023f3f322665cee1e6442d8cc68c78c83",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Mark 🎯T10 (Frontier K) as achieved",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T12:15:44Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "786a94da26e82aa9052a82fcad70f0923a90b262",
"body": "Replace the brief static MCP instructions with the full agents-guide\ncontent. Add a `get_agent_prompt` tool that returns the guide plus\ndynamic project-specific recipes and conventions from the store.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add agent prompt generation (Frontier K initial cut)",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T10:38:01Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6dad7c555920a16a2f425d8a3cfa9d6eb42e65a8",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Update audit log for corrected release",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T10:17:44Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "4eb969c0adead3b746c85045f99b66db230d547d",
"body": "- Add --help-agent CLI flag that prints help + agents-guide.md\n- Fix release workflow: use homebrew-releaser, correct asset naming\n (canopy-VERSION-os-arch.tar.gz), add test step, trigger on published\n- Add agent guide section to README\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add --help-agent flag, fix release workflow",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T10:17:10Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "918e553bb4c42d8c10cbc42e73410223d8953560",
"body": "Exhaustive inventory of CLI flags, MCP tool parameters, file formats,\nand store.db schema with stability classifications. Documents gaps\nand prerequisites for a future 1.0 release.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add STABILITY.md cataloguing public interaction surface",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T10:15:49Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6866502fd097ba3abfa160413208f7276008bd58",
"body": "Covers MCP setup, recommended workflow, tool reference with params,\nthe codegen ctx API, transform_fn node objects, and practical tips.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add agents-guide.md for AI coding agents using Canopy as MCP server",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T10:15:10Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "96d4699387f3ae6b651a927edc07dbef5d067363",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add audit log for open-source release",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T10:10:10Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "d6ba4ea5c81f0694b277a4aa2467a93bac7ea4d7",
"body": "- Fix 10 clippy lints (collapsible ifs, unnecessary cast, ptr_arg, etc.)\n- Apply rustfmt formatting\n- Add CI workflow (test, clippy, fmt on push/PR)\n- Add release workflow (cross-compile for macOS arm64, Linux amd64/arm64,\n Homebrew formula generation)\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fix clippy warnings, add CI and release workflows",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T10:03:54Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "0a66d16bc72a4a30ea0a65d8806c7755593795c8",
"body": "README covers features, quick start, MCP tool reference, architecture,\nand language support. CLAUDE.md documents build, project layout,\narchitecture, and conventions for agent use.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add README and CLAUDE.md for open-source release",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T09:38:29Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "f0623aa7868d242eceba0999fe68063aee5174d1",
"body": "- Add Apache 2.0 LICENSE file\n- Add crate-level #![allow(dead_code)] for planned API stubs\n- Remove unused imports (BufRead, LanguageAdapter)\n- cargo fix auto-corrections\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Prepare for open-sourcing: add LICENSE, clean up warnings",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T09:36:41Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "31f0cca2bb0640f577ea5c5f00f66cd2a70650bf",
"body": "polyrefactor → canopy, PolyRefactorServer → CanopyServer.\nBinary, store directory (.canopy/), backup files (.canopy.bak/new),\ndocs, CLI name, MCP server instructions all updated.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Rename to Canopy",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T09:19:56Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "eeda5a3e3ec7eb8a6fe12240222af44b8915fad5",
"body": "apply tool now:\n- Writes new content to .polyrefactor.new temp files first\n- Backs up originals to .polyrefactor.bak\n- Renames temp files to final paths (quasi-atomic)\n- Reports backup creation in output\n\nundo tool:\n- Restores from .polyrefactor.bak backup files\n- Handles new files (created by apply\n[…]\ncovery\n- Undo is always available for the last apply\n- Backup/temp files excluded from git via .gitignore\n\n23 MCP tools, 35 tests.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Add backup/undo safety system for apply",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T08:17:40Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "f4c72f276f46fb508cc2a98c13b03d600746425b",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Mark 🎯T9 (Frontiers D & E) as achieved",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T07:30:07Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "e392e064ab2af7e3358f534159c5bff9112332ff",
"body": "structural_checks() in codegen.rs:\n- Builds pre-change and post-change symbol indexes by re-parsing\n changed files' new_source\n- Detects removed symbols still referenced: if a function/type\n existed before but is missing after, and call sites still\n reference it, reports a warning\n- Only reports \n[…]\nition, call stays\n- structural_check_renamed_function_missing_call_update: rename def\n but leave old call site\n\n35 tests passing.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Frontier D: structural pre-flight checks for dangling references",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T07:29:53Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "68549761c3fa34b4f14eff9ac356e7b9032ffbed",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Update targets: Frontier E done, D in progress",
"author_name": "Marcelo Cantos",
"author_login": "marcelocantos",
"committed_at": "2026-04-05T07:29:28Z",
"body_truncated": false,
"is_coding_agent": true
}
],
"releases_count": 17,
"commits_last_year": 128,
"latest_release_at": "2026-07-18T21:35:31Z",
"latest_release_tag": "v0.17.0",
"releases_from_tags": false,
"days_since_last_push": 1,
"active_weeks_last_year": 10,
"days_since_latest_release": 7,
"mean_days_between_releases": 11.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/marcelocantos/sawmill",
"exists": true,
"license": null,
"keywords": [],
"ecosystem": "go",
"matches_repo": true,
"registry_url": "https://pkg.go.dev/github.com/marcelocantos/sawmill",
"is_deprecated": false,
"latest_version": "v0.17.0",
"repository_url": "https://github.com/marcelocantos/sawmill",
"versions_count": 17,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": null,
"latest_published_at": "2026-07-18T21:35:16Z",
"latest_version_yanked": null,
"days_since_latest_publish": 7
}
]
},
"popularity": {
"forks": 0,
"stars": 0,
"watchers": 0,
"fork_history": {
"days": [],
"complete": true,
"collected": 0,
"total_forks": 0
},
"star_history": {
"days": [],
"complete": true,
"collected": 0,
"total_stars": 0,
"collected_at": null
},
"open_issues_and_prs": 2
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [
"demos"
],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [
"Makefile"
],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [],
"toolchain_manifests": [
"go/go.mod"
],
"largest_source_bytes": 133259,
"source_files_sampled": 197,
"oversized_source_files": 2,
"agent_instruction_files": [
"CLAUDE.md"
],
"agent_instruction_max_bytes": 4025
},
"dependencies": {
"manifests": [
"go/go.mod"
],
"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"
],
"dependencies": [
{
"name": "github.com/fsnotify/fsnotify",
"manifest": "go/go.mod",
"ecosystem": "go",
"version_constraint": "v1.9.0"
},
{
"name": "github.com/go-git/go-billy/v5",
"manifest": "go/go.mod",
"ecosystem": "go",
"version_constraint": "v5.8.0"
},
{
"name": "github.com/go-git/go-git/v5",
"manifest": "go/go.mod",
"ecosystem": "go",
"version_constraint": "v5.17.2"
},
{
"name": "github.com/marcelocantos/claudia",
"manifest": "go/go.mod",
"ecosystem": "go",
"version_constraint": "v0.12.0"
},
{
"name": "github.com/mark3labs/mcp-go",
"manifest": "go/go.mod",
"ecosystem": "go",
"version_constraint": "v0.47.0"
},
{
"name": "github.com/odvcencio/gotreesitter",
"manifest": "go/go.mod",
"ecosystem": "go",
"version_constraint": "v0.15.2"
},
{
"name": "github.com/pmezard/go-difflib",
"manifest": "go/go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.0"
},
{
"name": "gopkg.in/yaml.v3",
"manifest": "go/go.mod",
"ecosystem": "go",
"version_constraint": "v3.0.1"
},
{
"name": "modernc.org/quickjs",
"manifest": "go/go.mod",
"ecosystem": "go",
"version_constraint": "v0.17.2"
},
{
"name": "modernc.org/sqlite",
"manifest": "go/go.mod",
"ecosystem": "go",
"version_constraint": "v1.48.1"
}
],
"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": 2,
"merged_prs": 35,
"open_issues": 0,
"closed_ratio": null,
"closed_issues": 0,
"closed_unmerged_prs": 0
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "marcelocantos",
"commits": 128,
"avatar_url": "https://avatars.githubusercontent.com/u/215143?v=4"
}
],
"contributors_sampled": 1,
"top_contributor_share": 1
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"go.yml",
"release.yml"
],
"has_docs_dir": true,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"go.sum"
],
"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": 10,
"reason": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
"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": 0,
"reason": "project has 0 contributing companies or organizations -- score normalized to 0",
"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": "13 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": null,
"reason": "packaging workflow not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 0,
"reason": "dependency not pinned by hash detected -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "SAST tool is not run on all commits -- score normalized to 0",
"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": "30 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "c7a3bef7642ea440c3b1b1e444b329d22e2f1a53",
"ran_at": "2026-07-26T08:27:18Z",
"aggregate_score": 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": "2026-07-18T21:38:09Z",
"oldest_open_prs": [
{
"number": 12,
"created_at": "2026-04-25T03:14:38Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 37,
"created_at": "2026-07-24T23:53:29Z",
"last_comment_at": null,
"last_comment_author": null
}
],
"last_merged_pr_at": "2026-07-18T21:35:17Z",
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/marcelocantos/sawmill",
"host": "github.com",
"name": "sawmill",
"owner": "marcelocantos"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 54,
"inputs": {
"security": 30,
"vitality": 79,
"community": 24,
"governance": 55,
"engineering": 71
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 79,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "good",
"name": "Development activity",
"note": null,
"notes": [],
"value": 71,
"inputs": {
"commits_last_year": 128,
"human_commit_share": 1,
"days_since_last_push": 1,
"active_weeks_last_year": 10
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 1 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 1
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "10/52 weeks with commits",
"points": 6.9,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 10
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "128 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 128
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "13 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": 17,
"latest_release_tag": "v0.17.0",
"releases_from_tags": false,
"days_since_latest_release": 7,
"mean_days_between_releases": 11.4
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "17 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 17
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 7 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 7
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~11.4 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 11.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": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "critical",
"name": "Community & Adoption",
"value": 24,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 1,
"inputs": {
"forks": 0,
"stars": 0,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "0 stars",
"points": 0,
"status": "missed",
"details": [
{
"code": "stars",
"params": {
"count": 0
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "0 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 0
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "0 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 0
}
}
],
"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 (Apache-2.0)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "Apache-2.0"
}
}
],
"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": 55,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 10,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 1,
"top_contributor_share": 1
},
"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 100% of commits",
"points": 0,
"status": "missed",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 100
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "1 contributors",
"points": 1.4,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 1
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 0 contributing companies or organizations -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "good",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"issue_resolution"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 72,
"inputs": {
"merged_prs": 35,
"open_issues": 0,
"closed_issues": 0,
"issue_closed_ratio": null,
"closed_unmerged_prs": 0
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "no issues or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_issues_or_data",
"params": {}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "35/35 decided PRs merged",
"points": 38.2,
"status": "met",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 35,
"decided": 35
}
}
],
"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": 57,
"inputs": {
"followers": 28,
"owner_type": "User",
"is_verified": null,
"owner_login": "marcelocantos",
"public_repos": 64,
"account_age_days": 5988
},
"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": "28 followers of marcelocantos",
"points": 10.5,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 28,
"login": "marcelocantos"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "64 public repos, account ~16 yr old",
"points": 25,
"status": "met",
"details": [
{
"code": "public_repos",
"params": {
"count": 64
}
},
{
"code": "account_age_years",
"params": {
"years": 16
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"github.com/marcelocantos/sawmill"
],
"ecosystems": "go",
"any_deprecated": false,
"min_days_since_publish": 7
},
"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 7 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 7
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "17 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 17
}
}
],
"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": 71,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 68,
"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": "2 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 2
}
}
],
"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": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
"points": 20,
"status": "met",
"details": [],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "good",
"name": "Documentation",
"note": null,
"notes": [],
"value": 75,
"inputs": {
"topics": [
"ai-agents",
"ast",
"code-generation",
"mcp",
"refactoring",
"rust",
"tree-sitter"
],
"has_wiki": false,
"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": "7 topics",
"points": 10,
"status": "met",
"details": [
{
"code": "topics_count",
"params": {
"count": 7
}
}
],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "at_risk",
"name": "Security",
"value": 30,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "at_risk",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): Packaging. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"packaging"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 30,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 17,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 1,
"scorecard_aggregate": 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": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
"points": 2.5,
"status": "met",
"details": [],
"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 0 contributing companies or organizations -- score normalized to 0",
"points": 0,
"status": "missed",
"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": "13 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 not detected",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool is not run on all commits -- score normalized to 0",
"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": "30 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": 2
},
"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": 75,
"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.86,
"agent_instruction_files": [
"CLAUDE.md"
],
"agent_instruction_max_bytes": 4025
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "CLAUDE.md",
"points": 45,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "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": "86 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 86,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "good",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 71,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"go.sum"
],
"has_dockerfile": false,
"typed_language": true,
"bootstrap_files": [
"Makefile"
],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [],
"agent_commit_share": 0.97,
"toolchain_manifests": [
"go/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": "lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "97 of the last 100 commits agent-authored or agent-credited",
"points": 10,
"status": "met",
"details": [
{
"code": "agent_authored_commits",
"params": {
"count": 97,
"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 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 99,
"inputs": {
"primary_language": "Go",
"largest_source_bytes": 133259,
"source_files_sampled": 197,
"oversized_source_files": 2
},
"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": "2/197 source files over 60KB",
"points": 54.4,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 197,
"oversized": 2
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "at_risk",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"example_dirs": [
"demos"
],
"has_mcp_signal": false,
"api_schema_files": []
},
"components": [
{
"key": "api_schema_openapi_graphql_proto",
"name": "API schema (OpenAPI/GraphQL/proto)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 40
},
{
"key": "mcp_server",
"name": "MCP server",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "runnable_examples",
"name": "Runnable examples",
"detail": "demos",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "demos"
}
}
],
"max_points": 40
}
]
}
],
"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": [
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
],
"report_type": "repository",
"generated_at": "2026-07-26T08:27:31.834870Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/m/marcelocantos/sawmill.svg",
"full_name": "marcelocantos/sawmill",
"license_state": "standard",
"license_spdx": "Apache-2.0"
}