原始 JSON 报告 机器可读
{
"data": {
"repo": {
"topics": [],
"is_fork": false,
"size_kb": 1000,
"has_wiki": true,
"homepage": "https://codeberg.org/merelinux/mere",
"languages": {
"Zig": 2931532,
"Shell": 1719,
"Python": 441,
"Vim Script": 4179
},
"pushed_at": "2026-07-21T02:04:13Z",
"created_at": "2019-08-23T14:17:58Z",
"owner_type": "User",
"updated_at": "2026-07-21T01:53:45Z",
"description": "A mirror repository for the mere package manager",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "Zig",
"significant_languages": [
"Zig"
]
},
"owner": {
"blog": "https://merelinux.org/",
"name": "Jeremy Huntwork",
"type": "User",
"login": "jhuntwork",
"company": null,
"location": "New York, NY",
"followers": 42,
"avatar_url": "https://avatars.githubusercontent.com/u/239626?v=4",
"created_at": "2010-04-08T15:38:11Z",
"is_verified": null,
"public_repos": 23,
"account_age_days": 5957
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v0.16.1",
"kind": "patch",
"published_at": "2026-07-21T01:53:28Z"
},
{
"tag": "v0.16.0",
"kind": "minor",
"published_at": "2026-07-21T00:57:08Z"
},
{
"tag": "v0.15.2",
"kind": "patch",
"published_at": "2026-07-18T18:15:34Z"
},
{
"tag": "v0.15.1",
"kind": "patch",
"published_at": "2026-07-18T16:10:39Z"
},
{
"tag": "v0.15.0",
"kind": "minor",
"published_at": "2026-07-18T01:07:42Z"
},
{
"tag": "v0.14.0",
"kind": "minor",
"published_at": "2026-06-04T17:07:24Z"
},
{
"tag": "v0.13.2",
"kind": "patch",
"published_at": "2026-06-01T00:59:01Z"
},
{
"tag": "v0.13.1",
"kind": "patch",
"published_at": "2026-05-28T14:36:43Z"
},
{
"tag": "v0.13.0",
"kind": "minor",
"published_at": "2026-05-20T13:47:43Z"
},
{
"tag": "v0.12.2",
"kind": "patch",
"published_at": "2026-04-04T22:38:04Z"
},
{
"tag": "v0.12.1",
"kind": "patch",
"published_at": "2026-04-03T22:47:41Z"
},
{
"tag": "v0.12.0",
"kind": "minor",
"published_at": "2026-04-03T21:44:43Z"
},
{
"tag": "v0.11.1",
"kind": "patch",
"published_at": "2026-04-03T18:13:09Z"
},
{
"tag": "v0.11.0",
"kind": "minor",
"published_at": "2026-04-02T13:33:43Z"
},
{
"tag": "v0.10.4",
"kind": "patch",
"published_at": "2026-04-01T16:52:10Z"
},
{
"tag": "v0.10.3",
"kind": "patch",
"published_at": "2026-03-31T20:05:26Z"
},
{
"tag": "v0.10.2",
"kind": "patch",
"published_at": "2026-03-31T02:13:54Z"
},
{
"tag": "v0.10.1",
"kind": "patch",
"published_at": "2026-03-30T22:15:20Z"
},
{
"tag": "v0.10.0",
"kind": "minor",
"published_at": "2026-03-30T20:02:54Z"
},
{
"tag": "v0.9.7",
"kind": "patch",
"published_at": "2026-03-29T21:51:08Z"
},
{
"tag": "v0.9.5",
"kind": "patch",
"published_at": "2026-03-29T21:20:46Z"
},
{
"tag": "v0.9.4",
"kind": "patch",
"published_at": "2026-03-29T20:43:20Z"
},
{
"tag": "v0.9.2",
"kind": "patch",
"published_at": "2026-03-29T20:10:42Z"
},
{
"tag": "v0.9.0",
"kind": "minor",
"published_at": "2026-03-26T02:50:55Z"
},
{
"tag": "v0.8.0",
"kind": "minor",
"published_at": "2026-03-25T04:53:51Z"
},
{
"tag": "v0.7.2",
"kind": "patch",
"published_at": "2026-03-25T04:23:58Z"
},
{
"tag": "v0.7.1",
"kind": "patch",
"published_at": "2026-03-25T02:16:48Z"
},
{
"tag": "v0.7.0",
"kind": "minor",
"published_at": "2026-03-24T03:48:10Z"
},
{
"tag": "v0.6.5",
"kind": "patch",
"published_at": "2026-03-23T12:38:57Z"
},
{
"tag": "v0.6.4",
"kind": "patch",
"published_at": "2026-03-22T01:16:16Z"
},
{
"tag": "v0.6.3",
"kind": "patch",
"published_at": "2026-03-22T00:35:11Z"
},
{
"tag": "v0.6.2",
"kind": "patch",
"published_at": "2026-03-21T21:46:50Z"
}
],
"recent_commits": [
{
"oid": "83bd82c434c2b7bcc854f6dc750206d970427025",
"body": null,
"is_bot": false,
"headline": "release: v0.16.1",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-21T01:53:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7e24d3858606250ce2b4754de08fcdf2deff433b",
"body": "…25) from fix/logical-store-symlinks into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/125",
"is_bot": false,
"headline": "Merge pull request 'Use logical store paths for profile symlinks' (#1…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-21T01:51:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "903be35af5b546236a37017c6bee6571211e6887",
"body": "Profile symlinks embedded the physical --root prefix\n({root}/mere/store/...), which dangles inside the build\nnamespace: it bind-mounts {root}/mere onto /mere, so the store\nis only reachable at /mere/store/..., not at the host path.\nexecve(\"/bin/sh\") then failed with ENOENT before any output,\nproduci\n[…]\n/\") logical and physical are\nidentical.\n\nVerified: full test suite passes and mere dev build --root now\nruns the build script (fails only on an unrelated utmpx.h/musl\nrecipe issue, out of scope here).",
"is_bot": false,
"headline": "Use logical store paths for profile symlinks",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-21T01:47:42Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6262108214248749ecbe2117698114cf82b209f3",
"body": "Bump version for automated release.\n\nUpdates README.md install-instructions download URLs to match.",
"is_bot": false,
"headline": "release: v0.16.0",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-21T00:57:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "92d0993768de30720d621cf61ce1536c67caf14f",
"body": "…namespace' (#124) from fix/namespace-mere-root-bind into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/124",
"is_bot": false,
"headline": "Merge pull request 'Use opts.mere_root instead of hardcoded /mere in …",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-21T00:55:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "954d6bc8f7cbb6e400e0f67d9bdb413949be8eef",
"body": "…23) from metadata-property-passthrough into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/123",
"is_bot": false,
"headline": "Merge pull request 'Pass recipe metadata through release publish' (#1…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-21T00:52:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a1f2c03b3ab12f1da6da45cdbb882e4ccb5b26b1",
"body": "buildSyntheticRoot bind-mounted the host's /mere unconditionally,\nwhich breaks when --root points to a different location. Profile\nsymlinks resolve against the store at the specified root, but the\nnamespace was mounting the wrong /mere over them.\n\nAdd mere_root field to EnvOptions (defaults to \"/mere\" for backward\ncompat). Both shell.zig and build_orchestrator.zig now pass\n{root}/mere derived from the --root flag.",
"is_bot": false,
"headline": "Use opts.mere_root instead of hardcoded /mere in namespace",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-21T00:50:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9e25a248a30aecf94a963f8c80348e8c311c4a08",
"body": "release publish was dropping the properties column when copying packages\nfrom the dev repo to the release output. Import correctly built and\nstored the metadata JSON (description, url, licenses, source_urls) from\nmeta.kdl, but publish passed null to insertPackageTransaction — so the\nrelease repo.db \n[…]\n→ dev repo properties column → release repo.db properties\ncolumn.\n\nVerified end-to-end via swamp mere-pkgd-e2e workflow: build → publish →\nquery properties column confirms all metadata fields present.",
"is_bot": false,
"headline": "Pass recipe metadata through release publish",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-19T17:15:00Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5ae686ef376b77dde7646aa79b555a225087a77a",
"body": "Reviewed-on: https://codeberg.org/merelinux/mere/pulls/122",
"is_bot": false,
"headline": "Merge pull request 'release: v0.15.2' (#122) from v0.15.2 into main",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-18T18:15:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6d6a52d67047ce657d571fcf0928fb53c882def8",
"body": "Bump version for automated release.\n\nUpdates README.md install-instructions download URLs to match.",
"is_bot": false,
"headline": "release: v0.15.2",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-18T18:11:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e405354b28bb8e33d79d83ecec23ffd15a3f03dc",
"body": "…from import-log-package-details into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/121",
"is_bot": false,
"headline": "Merge pull request 'Log package details on successful import' (#121) …",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-18T18:10:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f312cb79a5222b2072c6585a821e9d805c37de88",
"body": "Emit an info-level log line for each package as it is imported,\nshowing name, version, release, and architecture. Previously only\nthe total count was reported at the CLI level, with no per-package\nvisibility during the import process.",
"is_bot": false,
"headline": "Log package details on successful import",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-18T18:06:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4cf070582f6cba42150573e13fd5d707a6e143f8",
"body": "…20) from fix/prune-by-version-not-id into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/120",
"is_bot": false,
"headline": "Merge pull request 'Use version comparison for retention pruning' (#1…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-18T18:03:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7fe4aa04f5462d0e7e2e31352ed0f00d12f41132",
"body": "pruneOldVersions previously used ORDER BY id DESC to determine\nwhich packages to keep, meaning insertion order decided retention.\nIf packages were imported out of order, the newest version could\nbe pruned while an older one was kept.\n\nRewrite to fetch all versions for a (name, arch) pair, sort using\n[…]\ne resolver and\ngetLatestPackagesByNameArch), and prune everything below the top\nkeep_count.\n\nAlso fix collectPruneCandidates in release.zig to use the same\nversion-comparison approach for consistency.",
"is_bot": false,
"headline": "Use version comparison for retention pruning",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-18T17:59:44Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c60ae9e679a12ee0cd98da611508d02d68946d06",
"body": "Bump version for automated release.\n\nAlso, switch CI runners to docker-aarch64 where possible for faster\nbuilds. Extract test step into its own job on aarch64, gating both\nrelease builds. Only release-x86_64 stays on docker since it must\nproduce the x86_64 binary.\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/119",
"is_bot": false,
"headline": "v0.15.1 (#119)",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-18T16:10:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1d32ad0e095dceecc7232e87685ed3e3734bc139",
"body": "…ilding' (#118) from release-publish-merge-semantics into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/118",
"is_bot": false,
"headline": "Merge pull request 'Merge new packages into output DB instead of rebu…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-18T14:58:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "17b6c6b6c0ba018108a87211d0af76d403ed246a",
"body": "release publish no longer clears the output repo.db on every\ninvocation. Instead it preserves the existing published state and\nmerges in new packages from the dev repo, skipping duplicates.\n\nRetention (keep 3 per name+arch) is applied across the full output\nDB after insertion. Orphaned archive files\n[…]\nows.\n\nThis makes the output directory the single source of truth for what\nis currently published, allowing pkgd to treat the dev repo as an\nephemeral staging area rather than a persistent accumulator.",
"is_bot": false,
"headline": "Merge new packages into output DB instead of rebuilding",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-18T14:46:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bba6a369a247b1a03593128e6f9de7344d57bc6b",
"body": "Bump version for automated release.\n\nUpdates README.md's install-instructions download URLs to match.\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/117",
"is_bot": false,
"headline": "release: v0.15.0 (#117)",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-18T01:07:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "191acea802e09e26dd453f5fa80d0e98ac1db115",
"body": "…ease-publish into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/116",
"is_bot": false,
"headline": "Merge pull request 'Add mere release publish command' (#116) from rel…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-18T00:37:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "05820557275f84ea20f9da72daa239a4b122f9e6",
"body": "Implements specification 9.9 (Release Publication Requirements): a\nnew mere release publish --dev-repo --output [--key] command that\nbuilds a signed public release (repo.db, repo.db.sig, packages/) from\na dev repository as the sole source of truth, applying keep-count\nretention and failing loudly be\n[…]\nput are explicit, caller-supplied paths\nrather than workstation conventions, so this can run against\narbitrary directories in a server context (see the pkgd service,\nwhich shells out to this command).",
"is_bot": false,
"headline": "Add mere release publish command",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-17T21:16:21Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "27a727bbd32c94993ebe3eb2d881b6e2e10f7e5e",
"body": "… errors to FileSystem' (#115) from sign-verifysignature-error-mapping into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/115",
"is_bot": false,
"headline": "Merge pull request 'Stop collapsing verifySignature's public-key-load…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-15T21:41:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "982e7893bd056f8be66228be29496547498e4feb",
"body": "verifySignature caught every PublicKey.loadFromFile error and mapped\nit to a generic SignError.FileSystem, even though loadFromFile already\nreturns the fully-specific SignError itself - same pattern as\ngetFileHash. Propagate the error directly instead of remapping it.",
"is_bot": false,
"headline": "Stop collapsing verifySignature's public-key-load errors to FileSystem",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-13T18:23:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f99287aab69f2fa0b13e1481a3c407582c63f70e",
"body": "…sage' (#114) from extract-libarchive-message-strings into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/114",
"is_bot": false,
"headline": "Merge pull request 'Match libarchive's actual absolute-path error mes…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-13T17:27:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "07271d79f76b95bf109699469d093794c28cd3be",
"body": "classifyLibarchiveMessage checked for \"Absolute path\" and \"Bad path\",\nneither of which libarchive ever actually produces (checked against\nthe vendored 3.8.2 source: archive_write_disk_posix.c's\nARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS branch emits \"Path is\nabsolute\" via fsobj_error's \"%s%s\" concatenat\n[…]\nr anywhere in libarchive). Currently harmless since mere never\nsets that flag, but would silently fail to classify the message if\nit's added later for defense-in-depth. Fixed to match the real string.",
"is_bot": false,
"headline": "Match libarchive's actual absolute-path error message",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-13T16:26:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9a9121c22ffd3f93d77348878761a4b32f5a4934",
"body": "…air' (#113) from repo-history-atomic-commit into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/113",
"is_bot": false,
"headline": "Merge pull request 'Publish repo.db and repo.db.sig atomically as a p…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-13T00:22:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4244eb2d49253b15d87e17c8bc30f63614d08ac6",
"body": "Staged.commit published the staged db and sig via two independent,\nnon-atomic copyFile calls. A crash between them left a mismatched\npair on disk - fails closed (every subsequent verify rejects the\nmismatch) but leaves the repo unusable until manually re-signed.\n\nAdded replaceLiveDbAndSigWithRollback, mirroring repocache.zig's\nexisting replaceCachedDbAndSigWithRollback: back up whatever is\ncurrently live, rename the new db and sig into place, and roll back\nto the backups on any partial failure.",
"is_bot": false,
"headline": "Publish repo.db and repo.db.sig atomically as a pair",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-12T23:34:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a11408b36dbb3c2599ffa5384700a408040372a0",
"body": "…mentInternal' (#112) from kdl-parse-node-double-free into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/112",
"is_bot": false,
"headline": "Merge pull request 'Fix double-free of a KDL node on OOM in parseDocu…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-12T22:44:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "784df46d21238be773b0c4edd23f1a47bbb38613",
"body": "KDL_EVENT_START_NODE registered errdefer new_node.deinit() right after\nNode.init, but never cancelled it once new_node was successfully\nappended into nodes or parent.children. A later failure in the same\nbranch (node_stack.append OOMing) fired that errdefer and\nparseDocumentInternal's own nodes-clea\n[…]\nne node.\n\nFixed with the same appended-flag pattern already used elsewhere in\nthis codebase for this exact ownership-transfer shape: the errdefer\nonly fires if the node was never handed off to a list.",
"is_bot": false,
"headline": "Fix double-free of a KDL node on OOM in parseDocumentInternal",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-12T22:08:58Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ad9266aabdbf1e032e47aae32caef4faa82a85a1",
"body": "…) from build-cache-locking into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/111",
"is_bot": false,
"headline": "Merge pull request 'Add locking around the on-disk build cache' (#111…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-12T19:37:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0ec5033d61ac99453492337301a2b40d8dd6bdd5",
"body": "gc() and the various storeXForKey() functions mutated the same\non-disk trees (keys/, artifacts/) with zero coordination, unlike the\npackage store's Context.acquireStoreLock(). Two concrete races:\ngc() could delete a just-persisted artifact before its key record was\nwritten (self-healing - the next b\n[…]\nePackageArchiveForKey().\n\nclear() now skips deleting its own .lock file while iterating\ncache_root's entries, since that file is cache infrastructure the lock\njust created, not cache content to clear.",
"is_bot": false,
"headline": "Add locking around the on-disk build cache",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-12T17:27:01Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "af370e6803dbf815eaeb15927b95c368cd38bac8",
"body": "…rBuild; fix leaks and a double-free in repo_sources.zig' (#110) from repo-caches-diagnostic-context-guard into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/110",
"is_bot": false,
"headline": "Merge pull request 'Preserve diagnostic context in createRepoCachesFo…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-10T22:49:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "be29782f3f05a90e983b07357d57cd24e3f5584a",
"body": "…d a double-free in repo_sources.zig\n\ncreateRepoCachesForBuild unconditionally overwrote whatever diagnostic\ncontext repo_sources.createCaches already set (e.g. a specific repo\nname and \"failed to initialize repository cache\") with a generic\n\"config\"/\"failed to create repo caches from config\", incon\n[…]\nror after the second\n defer double-freed it.\n\nAlso fixed test_helpers.createTestRepoConfig, which referenced a\nnonexistent .ctx field on RepoConfig - needed for the new\ncreateRepoCachesForBuild test.",
"is_bot": false,
"headline": "Preserve diagnostic context in createRepoCachesForBuild; fix leaks an…",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-10T21:33:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "df5599acd1472d7aa2242db115530ecfa418c41e",
"body": "…e failure diagnostics' (#109) from namespace-phase-error-detail into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/109",
"is_bot": false,
"headline": "Merge pull request 'Include the specific namespace error name in phas…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-10T17:33:52Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a1b193cf902df2fe38d20e1f34d2f842b26a5590",
"body": "runOneNamespacePhase set a static \"failed to fork and enter env\" message\nregardless of which of namespace.EnvError's ~20 variants (uid-map\nfailure, overlayfs unavailable, disabled user namespaces, mount\nfailures, etc.) actually occurred, with no way for an operator to tell\nthem apart from the message alone. Interpolate @errorName(err) into the\ndiagnostic details via setDiagnosticContextFmt instead of the static\nstring.",
"is_bot": false,
"headline": "Include the specific namespace error name in phase failure diagnostics",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-10T17:04:26Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9c5dae61988390acbbb348b07d660b9ae07a1bd2",
"body": "…ileSystem error' (#108) from sign-getfilehash-error-mapping into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/108",
"is_bot": false,
"headline": "Merge pull request 'Stop collapsing getFileHash errors to a generic F…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-10T16:41:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "05a82d3bbb9e4c89eb966a5b3a6b588482f8e06e",
"body": "getFileHash's catch on hash.calculateFileHash mapped every possible\nerror - including OutOfMemory and PermissionDenied - to a generic\nSignError.FileSystem, discarding the specific error calculateFileHash\nhad already computed. This backs defaultSigner (used when signing repo\ndatabases), and repositor\n[…]\n is to\njust propagate the error directly instead of remapping it - the\nAccessDenied/EndOfStream/Unexpected branches being collapsed over were\nalready dead code, since HashError can never produce them.",
"is_bot": false,
"headline": "Stop collapsing getFileHash errors to a generic FileSystem error",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-10T16:10:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e1ec2dbaa8845ca537e2693b1860fdc3c6dd3b9e",
"body": "…on-bomb-sized payload' (#107) from extract-decompression-bomb-limit into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/107",
"is_bot": false,
"headline": "Merge pull request 'Reject archive entries that declare a decompressi…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-10T15:50:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2b20b06468eb3657aaea43cf7ecb00970ea68014",
"body": "extractWithLibarchive extracted every entry regardless of its declared\nuncompressed size, with no ceiling. The signed-install path is tempered\nby install.zig's whole-archive hash verification against trusted repo\nmetadata before extraction runs, but mere dev import (import.zig) and\nbuild-source unpa\n[…]\nhich\nrejects any entry whose archive_entry_size() exceeds a 4 GiB ceiling,\nwith a diagnostic message naming the entry and stating the declared\nsize and the limit rather than a generic \"invalid input\".",
"is_bot": false,
"headline": "Reject archive entries that declare a decompression-bomb-sized payload",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-10T15:24:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "375ab9de6a4a0164dc9ef829dfe2c6b579519ab6",
"body": "…on restore' (#106) from build-cache-archive-restore-verify into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/106",
"is_bot": false,
"headline": "Merge pull request 'Re-verify cached archive hash before trusting it …",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-10T13:52:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "eef3869fc86a2f54253912da324761ac889af8cf",
"body": "restorePackageArchiveForKey copied a cached package archive out of the\nbuild cache and returned its recorded archive_hash/signature verbatim,\nwith no check that those still matched the file's actual bytes. This\nwas asymmetric with storePackageArchiveForKey, which does verify before\ncaching. If the c\n[…]\nnow returns null instead of a mismatched hash/signature pair. Verified\nthe test fails without the fix (a non-null result is returned and\nleaked, since nothing frees a hit the caller wasn't expecting).",
"is_bot": false,
"headline": "Re-verify cached archive hash before trusting it on restore",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-10T13:32:25Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d8fb21e64aa77e97dff10514ea93e4054ab7eae4",
"body": "…ntinueOnError' (#105) from split-staging-partial-cache into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/105",
"is_bot": false,
"headline": "Merge pull request 'Don't cache a partial split-stage result under Co…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-10T13:02:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "835fbb69c4ba6e3fd720ad9f355506938c45167d",
"body": "Under FailurePolicy.ContinueOnError, stageSplitPackages can skip a\nsub-package that failed to stage and still return successfully (the\nerror is only recorded via split_staging_errors_encountered).\nrestoreOrStageSplitPackages unconditionally persisted that result to\nthe build cache regardless of the \n[…]\nkages, forcing one package to\nfail on the first call only. Verified the test fails without the fix\n(the second call restores the cached 1-package result instead of\nre-staging both) and passes with it.",
"is_bot": false,
"headline": "Don't cache a partial split-stage result under ContinueOnError",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-10T12:14:25Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ce618c0dd8e9154d35d27813187f08e237feaef6",
"body": "…rtifact' (#104) from packaging-archive-hash-double-free into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/104",
"is_bot": false,
"headline": "Merge pull request 'Fix double-free of archive_hash in createPackageA…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-10T02:11:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7ca3c456436fb0dae08314bb180acc658de3e3f0",
"body": "Two late-stage error branches in createPackageArtifact (the\nresult_package_name and result_signature dupe failures) manually freed\narchive_hash even though an errdefer registered earlier for archive_hash\nwas still armed, causing a double-free when OOM struck at either of\nthose two allocation sites.\n\n[…]\n to\ndeterministically reproduce the double-free. Verified the test fails\nagainst the unfixed code (GeneralPurposeAllocator reports the double\nfree at the exact two call sites) and passes with the fix.",
"is_bot": false,
"headline": "Fix double-free of archive_hash in createPackageArtifact",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-10T01:47:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "37bda82b7f1eb1768fcb771a3d9e289a26e8afe7",
"body": "…y versions, not names' (#103) from build-cache-dependency-versions into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/103",
"is_bot": false,
"headline": "Merge pull request 'Key the build profile cache on resolved dependenc…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-10T01:18:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "06b2f123d3d78dadf7488355e648667141d49d84",
"body": "computeProfileRealizeKey hashed a recipe's dependency *names* but never\nthe versions actually resolved for them. Dependency resolution is\ndynamic (an unpinned \"openssl\" resolves to whatever's newest in the\nsynced repo), so a repo sync that bumps a build-time dependency to a\nnew version was invisible\n[…]\nther than a second repo sync.\n\nAdded a regression test proving the key changes when a dependency's\nresolved content hash changes (and stays stable when it doesn't);\nconfirmed it fails without the fix.",
"is_bot": false,
"headline": "Key the build profile cache on resolved dependency versions, not names",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-10T00:34:04Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "67eeb7d8c1b88d0e9bc95be970cd654763035ae6",
"body": "…fore touching the store' (#102) from pin-profile-store-lock into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/102",
"is_bot": false,
"headline": "Merge pull request 'Acquire the store lock in pin/profile commands be…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-09T22:50:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bab6852428ac8942e95b21cab4b853be01e21261",
"body": "pin add, profile create --from, profile apply, and profile delete all\ncreate or reference store content or gc-roots without holding the\nstore lock that install/uninstall/generation commands already use. A\nconcurrent mere store clean's mark phase can miss a store path these\ncommands are about to refe\n[…]\nat pre-creates a valid, real store path (so\npin.create would legitimately succeed if reached) and blocks lock\nacquisition by pre-creating mere/.lock as a directory; confirmed it\nfails without the fix.",
"is_bot": false,
"headline": "Acquire the store lock in pin/profile commands before touching the store",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-09T21:48:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f41648ebc0426261b4c18939a9050aab079522a0",
"body": "…tParser.parse' (#101) from parser-end-of-flags-separator into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/101",
"is_bot": false,
"headline": "Merge pull request 'Handle -- as an end-of-flags separator in Argumen…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-09T15:51:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "58fcca708cc4102da56d064d0b664872fe5690a2",
"body": "ArgumentParser.parse had no handling for a literal \"--\" argument: it\nwould be matched by the startsWith(arg, \"--\") long-flag branch with an\nempty flag name and rejected as InvalidInput. cli.zig's one current\ncaller happens to strip \"--\" and everything after it before calling\nparse(), so this never s\n[…]\n\nAdded src/cli/parser.zig to build.zig's test_modules (same pattern as\ncommand.zig) since it had no test coverage at all; added tests\ncovering the new -- handling, confirmed they fail without the fix.",
"is_bot": false,
"headline": "Handle -- as an end-of-flags separator in ArgumentParser.parse",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-09T15:33:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ea14fe30807d4c1a65ef04976a0b0da9b193ccb3",
"body": "…f curl+sha256sum' (#100) from vendor-deps-build-zig-zon into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/100",
"is_bot": false,
"headline": "Merge pull request 'Fetch vendored C deps via build.zig.zon instead o…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-09T15:15:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bc738e90301f36bdf538ec8440302f8f04a1b92d",
"body": "Source acquisition for the vendored C libraries was a hand-rolled\nshell script (curl + sha256sum + tar) run at build time, participating\nin none of Zig's package infrastructure: no global cache dedup, no\n`--fetch` offline-build support, and a checksum format (sha256 hex)\nduplicating what Zig's own f\n[…]\n.zon's shape (only\n.version is ever read), which broke the moment .dependencies was\nadded. Letting Zig infer the type from the import directly makes it\nrobust against future build.zig.zon changes too.",
"is_bot": false,
"headline": "Fetch vendored C deps via build.zig.zon instead of curl+sha256sum",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-09T14:42:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "caec571e923c569303832e737d319e0d147d60a1",
"body": "…cond disk read' (#99) from repo-db-verify-deserialize into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/99",
"is_bot": false,
"headline": "Merge pull request 'Open cached repo.db from verified bytes, not a se…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-09T03:18:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "651c505e6b00c91d29c9502d86749a40d552a3c7",
"body": "RepoCache.ensureRepository hashed repo.db to verify its signature and\nthen let Repository.init reopen the same path fresh via sqlite3_open_v2,\nuntied to the hash that had just been checked. A file swapped in that\nwindow would make the verification meaningless for whatever sqlite\nactually read.\n\nsign\n[…]\nead the verified bytes through to this new path; the two\nother verifyWithTrustedFingerprints callers (repo_sources.zig,\nsyncLocal's download-then-rename flow) just needed to free the new\nreturn field.",
"is_bot": false,
"headline": "Open cached repo.db from verified bytes, not a second disk read",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-09T03:03:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c504a31a2fb34ef68683d8f2e12a51080299cef3",
"body": "…re dev import' (#98) from import-verify-before-parse into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/98",
"is_bot": false,
"headline": "Merge pull request 'Verify manifest signature before parsing it in me…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-09T02:30:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fe17e830666c2b81a488d61d63cf03ad5a4f3a81",
"body": "prepareVerifiedImport built a Package struct from the manifest before\nchecking its signature at all: readManifestAndCreatePackage decoded\nand used manifest.v1 first, and verifyManifestSignatureAndGetSigner\nonly checked the signature afterward against a separate fresh read.\nUntrusted content got pars\n[…]\ng the file\nagain. A malformed manifest with no valid signature is now rejected\nas SignatureInvalid rather than leaking InvalidInput from decoding\nuntrusted bytes before the signature was ever checked.",
"is_bot": false,
"headline": "Verify manifest signature before parsing it in mere dev import",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-09T02:17:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "16866d641dd56acbc2db4ad2a2cb630d65dfc04e",
"body": "…not a second disk read' (#97) from manifest-verify-toctou into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/97",
"is_bot": false,
"headline": "Merge pull request 'Parse manifest.v1 from the exact bytes verified, …",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-09T01:35:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cbfe0ca354bf3092213aafec2cb9e59dc2e3d5b4",
"body": "Manifest signature verification hashed/verified the file's bytes in\nmemory and then discarded them; the caller separately re-opened and\nre-read the same path to get bytes for parsing. Swapping the file's\ncontent in that window would make the verified signature meaningless\nfor whatever actually got p\n[…]\nmselves (owned by ctx.allocator) instead of just a fingerprint, so\ninstall.zig can decode the manifest directly from them. Updated the\nother two callers (import.zig, verify.zig) to free the new field.",
"is_bot": false,
"headline": "Parse manifest.v1 from the exact bytes verified, not a second disk read",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-09T01:13:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0121943bc849df74ff3015f7fec507ab11717abd",
"body": "…before/after atomic rename' (#96) from fsync-store-admission into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/96",
"is_bot": false,
"headline": "Merge pull request 'fsync staged package content and store directory …",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-09T00:41:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b8ab09a4275ec30a0f9944ae8e917bbd0fe00c6e",
"body": "…rename\n\nStore admission renamed staged package content into its final\ncontent-addressed path with no fsync anywhere in the sequence, so a\npower loss right after \"install succeeded\" could leave a store object\nwith truncated or corrupted data despite appearing to exist. Recursively\nfsync the staging tree's file data and directory entries before the\nrename, and fsync the store's parent directory afterward to make the\nrename itself durable.",
"is_bot": false,
"headline": "fsync staged package content and store directory before/after atomic …",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-09T00:07:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6f293ff61a9ef1cb6a1830da792f5c51580ebc70",
"body": "…ardcoded exit codes' (#95) from cli-error-boundary-helper into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/95",
"is_bot": false,
"headline": "Merge pull request 'Consolidate CLI error-boundary handling and fix h…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-08T23:09:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a58c162136b186b32a97bbb32b3e89606866b24f",
"body": "install.zig, uninstall.zig, profile.zig, and shell.zig each duplicated\nthe same ~30-line block mapping a caught error to a CommandResult:\nresolve the diagnostic context, format a user-friendly message, dupe\nit, done. Every call site hardcoded exit_code = 1 regardless of the\nactual error, so a Permis\n[…]\nd Zig 0.16 rejects that for a standalone test root). Added real\nregression tests for errorResult's exit-code mapping and diagnostic\ncontext folding; confirmed the exit-code test fails without the fix.",
"is_bot": false,
"headline": "Consolidate CLI error-boundary handling and fix hardcoded exit codes",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-08T22:17:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "51dbb52870ebd92f99d57ada9b9bb51bfd27907c",
"body": "…le with a passthrough command' (#94) from shell-passthrough-profile-arg into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/94",
"is_bot": false,
"headline": "Merge pull request 'Fix mere shell ignoring the positional profile fi…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-08T21:43:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ddf79419fb99588511536cacd9eb9604189f7f7d",
"body": "…h command\n\nresolveProfileName only consulted the positional profile.kdl argument\nwhen args.passthrough was empty, but the command's own usage message\ndocuments the file and a passthrough command being used together\n(`mere shell [profile.kdl] -- <command> [args...]`). Using that\ndocumented form sile\n[…]\nperly-scoped\nsrc/cli/-rooted module wired through build.zig - worth doing, but a\nseparate piece of work from this fix. Verified manually by tracing the\nbefore/after logic against the documented usage.",
"is_bot": false,
"headline": "Fix mere shell ignoring the positional profile file with a passthroug…",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-08T20:31:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "49aff509c43d960d828aa516f08b35e835710dd5",
"body": "…y-required packages' (#93) from uninstall-cascade-multiple-packages into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/93",
"is_bot": false,
"headline": "Merge pull request 'Fix uninstall --cascade for multiple independentl…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-08T18:23:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ddfc9768e536cd3aa232f88834b5aaf8e9292946",
"body": "Cascade only ever accounted for the first requested package still\nfound in the resolution: it computed one cascade round, re-resolved\nonce, then unconditionally broke out of the loop. A second requested\nremoval still pulled in by a different, unrelated dependent was never\nre-checked against the new \n[…]\n roots left to re-resolve.\n\nAdded a regression test with two packages independently required by\ndifferent dependents; confirmed it reproduces both bugs independently\nbefore landing the fix for either.",
"is_bot": false,
"headline": "Fix uninstall --cascade for multiple independently-required packages",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-08T18:13:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "92b36634199bd5d8bcb28e04b9a3d923cc4624e2",
"body": "…rsions' (#92) from fix-cross-package-provider into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/92",
"is_bot": false,
"headline": "Merge pull request 'Fix cross-package provider selection comparing ve…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-04T12:58:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "950a080d3e57d962a5fb9e7b3c1f0e1ae658ebb4",
"body": "When multiple packages provide the same soname (e.g. libglvnd and\nmesa both providing libEGL.so.1), compareCandidates sorted them by\nversion number. This is meaningless across different package names —\n\"26.0.3\" vs \"1.7.0\" says nothing about which is the better provider.\nThe result was that mesa alwa\n[…]\ner than hiding it behind\nmeaningless version comparison.\n\nTests:\n- Cross-package providers, different priority -> higher-priority wins\n- Cross-package providers, same priority -> ConflictingProvisions",
"is_bot": false,
"headline": "Fix cross-package provider selection comparing versions",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-04T04:14:53Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "59d8878e927ba6cec3061236eb507a839d7f1676",
"body": "…not just on download' (#91) from reverify-cached-repo-db into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/91",
"is_bot": false,
"headline": "Merge pull request 'Re-verify cached repo.db every time it's opened, …",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-03T19:56:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7510358b2c61abb31be14914ca7e4ce42b99cf37",
"body": "sync() only verified signatures when it actually downloaded a fresh\ndb. Once cached, a repo.db was trusted forever afterward with no\nre-check - ensureRepository() just opened it. A repo.db tampered with\ndirectly on disk after being verified (local attacker, or corruption)\nwould go undetected on ever\n[…]\nall.zig\nand search.zig.\n\nAdded a regression test: a repo verified once, then tampered with\non-disk without a following sync, must be rejected on the next fresh\nopen. Verified it fails without the fix.",
"is_bot": false,
"headline": "Re-verify cached repo.db every time it's opened, not just on download",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-03T16:30:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e00173c905e99ff6deaf20bcbe196c0b6dc89eb3",
"body": "…onfig.kdl' (#90) from verify-local-repo-signature into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/90",
"is_bot": false,
"headline": "Merge pull request 'Verify signatures for file:// repos declared in c…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-03T14:44:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0c29606496be35c0affb8b09d24aac1e6f98a54a",
"body": "syncLocal() was a no-op: sync() on a local (file://) repo never\nverified anything. Auto-discovered dev repos under /mere/dev/repo/\nare safe because repo_sources.zig verifies before ever constructing a\nRepoCache, but a file:// repo declared directly in config.kdl reached\nthis path with its own truste\n[…]\nlocal sync verified nothing.\nFixed both to sign the file that's actually read. Added a regression\ntest proving a local repo signed with an untrusted key is rejected;\nverified it fails without the fix.",
"is_bot": false,
"headline": "Verify signatures for file:// repos declared in config.kdl",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-03T14:25:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d07c11f5e119850f00a22c7343bb83c4fb92784c",
"body": "…from generation-keep-gc-root into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/89",
"is_bot": false,
"headline": "Merge pull request 'Create GC roots when keeping a generation' (#89) …",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-03T13:29:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "13604e6d12b0efcf727e9a4c4f5cc2575a5662c5",
"body": "…from remove-system-init-flag into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/88",
"is_bot": false,
"headline": "Merge pull request 'Remove --system flag from mere store init' (#88) …",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-03T13:18:12Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e3731bb33872c0d724dfdbceb7275b5bdfa83aa7",
"body": "createSystemLayout operated on hardcoded absolute host paths (/bin,\n/lib, /etc, ...) regardless of --root, making it the only place in the\ncodebase that could touch the real host filesystem instead of staying\nscoped to the configured root - and a real risk when bootstrapping a\nnew system into a moun\n[…]\nnagement and belongs in a separate installer,\nwhich will need to exist anyway. mere store init now only ever touches\npaths under --root.\n\nNo dedicated tests existed for --system or createSystemLayout.",
"is_bot": false,
"headline": "Remove --system flag from mere store init",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-03T13:06:45Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d9b5bc7a1a9edfaaf7a7c6e7c176eda85c9dd3ee",
"body": "…kages' (#87) from verify-archive-hash-before-extract into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/87",
"is_bot": false,
"headline": "Merge pull request 'Verify archive_hash before caching downloaded pac…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-03T12:49:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3858051761434d4e2ae9515cf05fb3b7db2a0a13",
"body": "prefetchMissingPackageArchives and ensurePackageArchiveCached both\ndownloaded package archives with DownloadOptions{} - no expected_hash -\neven though the signed repo db already carries the correct archive_hash\nfor every package. A tampered mirror or corrupted transfer would be\nsilently cached and l\n[…]\nt\ndidn't match their dummy archive bodies; fixed them to use the real\nhash of the body now that it's actually checked. Added a regression\ntest that a tampered archive gets rejected before it's cached.",
"is_bot": false,
"headline": "Verify archive_hash before caching downloaded packages",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-03T12:18:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9d03ab04dbda12b926f0031c661d4fa7eddaa836",
"body": "handleKeep only wrote the .keep marker file, never a GC-root symlink.\nmere store clean's reachability walk only follows gc-roots symlinks, so\na kept generation's directory would survive pruning but the store\nobjects it references would still get deleted - breaking the advertised\nrollback. Sync GC roots via gcroots.updateRoots (which already accounts\nfor explicit keeps) right after keepGeneration/unkeepGeneration.",
"is_bot": false,
"headline": "Create GC roots when keeping a generation",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-02T17:10:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1876cf92eb139d3426a766247e2be8e81bd89565",
"body": "…otless-store-init into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/85",
"is_bot": false,
"headline": "Merge pull request 'Allow rootless mere store init' (#85) from fix/ro…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-02T16:42:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "affef78407bf9eb0b4577e491d196c0aff341473",
"body": "…ce log error handling' (#86) from fix/store-mutation-locking into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/86",
"is_bot": false,
"headline": "Merge pull request 'Serialize mutating store operations and fix servi…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-07-02T16:41:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "35e78a3826c5b506c71d15a5582b27f0d76865fb",
"body": "Add a process-wide store lock (blocking exclusive flock on\n<root>/mere/.lock, reentrant within a Context) and wire it into every\nmutating command: install, uninstall, store generation\nactivate/keep/unkeep/delete, and store clean. Concurrent mere\ninvocations against the same root were previously unse\n[…]\net unnarrowed - only the exe target reaches this\npath, so zig build test never caught it) and a diagnostic-swallowing\nbug in serviceFailure's PermissionDenied branch that dropped context\nset upstream.",
"is_bot": false,
"headline": "Serialize mutating store operations and fix service log error handling",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-07-02T16:29:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f7762666c7f623c94e38e519d1d303a204a8b379",
"body": "`mere store init` gated on uid 0 and unconditionally chowned every\ndirectory to root:root. With a user-writable MERE_ROOT this gating\ncontributed nothing (filesystem permissions already control access)\nbut it blocked rootless installs entirely.\n\n- Drop the uid 0 check in `init.initialize()`. Filesys\n[…]\nre-test profile create test` succeeds\n- `mere --root /tmp/mere-test install -p test busybox` downloads,\n signature-verifies, extracts to store, materializes profile\n- Profile binary runs without sudo",
"is_bot": false,
"headline": "Allow rootless mere store init",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-26T19:34:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8a1dc01df76a5c545c035659205ecf688e51e6f3",
"body": "…refactor/drop-rollback-protection into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/84",
"is_bot": false,
"headline": "Merge pull request 'Drop rollback protection enforcement' (#84) from …",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-06-25T14:28:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "946f7870c2912a559461e287e28b84136744432d",
"body": null,
"is_bot": false,
"headline": "Merge branch 'main' into refactor/drop-rollback-protection",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-06-25T13:58:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "709a3a84b164c726fa64a93bd0b850f58c2752f1",
"body": "… refactor/declared-arch-only into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/83",
"is_bot": false,
"headline": "Merge pull request 'Require explicit package architecture' (#83) from…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-06-25T13:57:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "09a3b8e72cca94671498d0ca2ec965ff5a92d57b",
"body": "Rollback protection turned out to be a poor fit for Mere at its\ncurrent scale. The protection it offered (rejecting older signed\npackages on install) defends against a narrow attack: a mirror or\nnetwork attacker substituting an older, validly-signed package for\na newer one. With one repo, one signin\n[…]\nollback bullets and prose throughout\n- Mark created_at as informational\n\nManifest schema is unchanged. Generation rollback (the user-facing\nmere store generation activate flow) is unrelated and stays.",
"is_bot": false,
"headline": "Drop rollback protection enforcement",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-25T13:55:06Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3375335359a24ebdabf738a6d0592653cc8c35c6",
"body": "Recipes now declare which architectures they support. The\nprevious design tried to infer the target arch from package\ncontents, with \"any\" as a fallback when nothing was\ndetectable. That experiment didn't pay off. Auto-detection\nconfirmed what was already known in the easy cases, but got\nit wrong in\n[…]\nit is simpler and safer. \"any\" is now an opt-in\nclaim that a recipe author makes deliberately. Without a\ndeclaration, a package takes the build host's architecture.\n\nDependency inference is unchanged.",
"is_bot": false,
"headline": "Require explicit package architecture",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-25T12:49:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fdbc5c8268fcd97972addd4363cb0fbf10abc641",
"body": "…er-abstraction into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/82",
"is_bot": false,
"headline": "Merge pull request 'init provider abstraction' (#82) from init-provid…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-06-09T15:57:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "390c20204f9a9be515a40f7f623a57828ad82f3f",
"body": "Keep init-provider configuration errors specific as they pass through service management. Service commands now report unsupported configured providers and format config diagnostics instead of collapsing provider and config failures into generic service errors.\n\nAlso include the invalid provider value in config diagnostics so mistakes point directly at the setting that needs correction.",
"is_bot": false,
"headline": "Preserve service provider diagnostics",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-09T11:54:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d9dd0c8e5321141093b74d22ef402b9202111db3",
"body": "Add a typed init-provider setting to Mere configuration and route both runtime service commands and package-time service artifact generation through it.\n\ns6-rc remains the default and only implemented provider. dinit is recognized as a provider name, but selecting it now fails explicitly at the provider boundary instead of silently emitting or executing s6-rc behavior.\n\nAlso include services.zig in the aggregate test root so service facade tests run with the full suite.",
"is_bot": false,
"headline": "Wire init provider selection",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-09T11:54:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "35e62f7eb4cecc95f0707a76496922cb667bae9e",
"body": "Add an active-provider entry point for package-time service artifact generation and move the existing s6-rc source directory writer behind s6-rc-specific function names.\n\nBehavior is unchanged: recipe service blocks still emit s6-rc source directories under usr/share/s6-rc/sources. This makes the package-time provider boundary explicit before adding alternate artifact generators such as dinit.",
"is_bot": false,
"headline": "Name s6-rc service artifact generation",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-09T11:54:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "43a215b03fc1ea44102ad1802035f8713ea268c1",
"body": "Move service command handling behind a provider-neutral services module. The CLI no longer issues s6-rc commands directly for lifecycle, status, listing, or log operations; it delegates to src/services.zig instead.\n\nThe current provider remains s6-rc and behavior is intended to stay the same. This creates the runtime boundary needed before adding alternate init providers such as dinit.",
"is_bot": false,
"headline": "Introduce service provider facade",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-09T11:54:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "42c2118ce9f1cfeb7afa694cb5b334f1c93e4ef4",
"body": "…#81) from fix/bubble-file-hash-errors into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/81",
"is_bot": false,
"headline": "Merge pull request 'Bubble file path into calculateFileHash errors' (…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-06-09T11:49:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bb7e47c03825bf216ff54e261182c5e033d0f329",
"body": "calculateFileHash now takes *Context instead of Allocator and calls\nctx.setDiagnosticContext with the failing path and original error name\non any I/O failure. This ensures users see which file failed and why,\nrather than a generic \"filesystem error\" with no context.\n\nAlso removes redundant allocator\n[…]\npy,\nwhich caused arena allocations to escape cleanup.\n\nRoot cause of #75: missing signing key mapped FileNotFound to FileSystem\nwith no path context preserved. User now sees the actual path and error.",
"is_bot": false,
"headline": "Bubble file path into calculateFileHash errors",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-08T17:11:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "dfae3e9a62f6d58304fcb67bccc2e030fd472f7a",
"body": "Reviewed-on: https://codeberg.org/merelinux/mere/pulls/80",
"is_bot": false,
"headline": "Merge pull request 'release: v0.14.0' (#80) from v0.14.0 into main",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-06-04T17:07:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8e49dfe30bfcaecf08ce546a9d2ec419b7423cbf",
"body": null,
"is_bot": false,
"headline": "release: v0.14.0",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-04T16:45:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c3dc7f90854363f0221e569c9847c957fe61750f",
"body": "…ror-messages into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/79",
"is_bot": false,
"headline": "Merge pull request 'fix/cache-error-messages' (#79) from fix/cache-er…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-06-04T16:44:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b5411fa19b77f3e7448d6050eb048eb4e43820dc",
"body": "The rootless support PR (#78) added a guard that skips\nrollback-state updates when running unprivileged. The\nexisting \"fails hard on rollback-state update after\nadmission\" test relied on running unprivileged and chmod'ing\nthe cache directory to trigger PermissionDenied — the new\nguard makes that pat\n[…]\nvileged, finalizeAdmittedStoreObject succeeds and\ndoes not write a rollback-state file. Error propagation in\nthe privileged path is the standard switch-and-return pattern\nused throughout the codebase.",
"is_bot": false,
"headline": "Test the rootless guard in finalizeAdmittedStoreObject",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-04T16:36:30Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ed85634accaecfebee375ad160869379569952fb",
"body": "When restorePackageArchiveRequest failed, the same generic\n\"failed to resolve package cache\" message was returned for\nevery CacheError variant (OutOfMemory, FileSystem,\nPermissionDenied, InvalidInput). Users hitting the failure\nhad no way to tell whether they were looking at a permissions\nproblem, a\n[…]\nOOM, or invalid input.\n\nReplace the catch-all `else` branch with explicit handling\nof each variant, surfacing a distinct hint in the diagnostic\nmessage. The PackageError mapping is unchanged.\n\nRef #75",
"is_bot": false,
"headline": "Distinguish CacheError variants in package staging",
"author_name": "Jeremy Huntwork",
"author_login": "jhuntwork",
"committed_at": "2026-06-04T16:36:30Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "34d84905b559b7c2c262c746cb386cb69657d06a",
"body": "…t into main\n\nReviewed-on: https://codeberg.org/merelinux/mere/pulls/78",
"is_bot": false,
"headline": "Merge pull request 'rootless-support' (#78) from feat/rootless-suppor…",
"author_name": "jhuntwork",
"author_login": null,
"committed_at": "2026-06-03T23:31:03Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 32,
"commits_last_year": 272,
"latest_release_at": "2026-07-21T01:53:28Z",
"latest_release_tag": "v0.16.1",
"releases_from_tags": true,
"days_since_last_push": 10,
"active_weeks_last_year": 14,
"days_since_latest_release": 10,
"mean_days_between_releases": 11.9
},
"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": []
},
"popularity": {
"forks": 0,
"stars": 5,
"watchers": 2,
"fork_history": {
"days": [],
"complete": true,
"collected": 0,
"total_forks": 0
},
"star_history": null,
"open_issues_and_prs": 0
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [],
"toolchain_manifests": [],
"largest_source_bytes": 441,
"source_files_sampled": 1,
"oversized_source_files": 0,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [],
"advisories": {
"error": "No resolved dependencies to assess",
"scope": "repository_graph",
"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": [],
"dependencies": [],
"all_dependencies": {
"error": null,
"source": "github-sbom",
"packages": [],
"collected": true,
"truncated": false,
"total_count": 0,
"direct_count": 0,
"indirect_count": 0
}
},
"maintainership": {
"issues": {
"open_prs": 0,
"merged_prs": 15,
"open_issues": 0,
"closed_ratio": 1,
"closed_issues": 1,
"closed_unmerged_prs": 0
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "jhuntwork",
"commits": 167,
"avatar_url": "https://avatars.githubusercontent.com/u/239626?v=4"
}
],
"contributors_sampled": 1,
"top_contributor_share": 1
},
"quality_signals": {
"has_ci": false,
"has_tests": true,
"ci_workflows": [],
"has_docs_dir": true,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": null,
"reason": "no pull request found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 0,
"reason": "Found 0/30 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 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": null,
"reason": "no workflows found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 0,
"reason": "no update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 10,
"reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": null,
"reason": "packaging workflow not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": null,
"reason": "no dependencies found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "no SAST tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 0,
"reason": "security policy file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": null,
"reason": "no releases found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": null,
"reason": "No tokens found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 10,
"reason": "0 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "83bd82c434c2b7bcc854f6dc750206d970427025",
"ran_at": "2026-07-31T12:16:29Z",
"aggregate_score": 3.7,
"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-21T01:53:43Z",
"oldest_open_prs": [],
"last_merged_pr_at": "2024-07-23T04:12:55Z",
"ci_last_conclusion": null,
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/jhuntwork/mere",
"host": "github.com",
"name": "mere",
"owner": "jhuntwork"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"security": 37,
"vitality": 75,
"community": 29,
"governance": 48,
"engineering": 54
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 75,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "moderate",
"name": "Development activity",
"note": null,
"notes": [],
"value": 66,
"inputs": {
"commits_last_year": 272,
"human_commit_share": 1,
"days_since_last_push": 10,
"active_weeks_last_year": 14
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 10 days ago",
"points": 28.8,
"status": "partial",
"details": [
{
"code": "push_recency",
"params": {
"days": 10
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "14/52 weeks with commits",
"points": 9.7,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 14
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "272 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 272
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 88,
"inputs": {
"releases_count": 32,
"latest_release_tag": "v0.16.1",
"releases_from_tags": true,
"days_since_latest_release": 10,
"mean_days_between_releases": 11.9
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "32 version tags (no GitHub releases)",
"points": 16.2,
"status": "partial",
"details": [
{
"code": "version_tags_no_releases",
"params": {
"count": 32
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 10 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 10
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~11.9 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 11.9
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "maintained",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": null,
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": 10,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "last human commit 10 days ago",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_maintained",
"params": {
"days": 10
}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "critical",
"name": "Community & Adoption",
"value": 29,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 10,
"inputs": {
"forks": 0,
"stars": 5,
"watchers": 2,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "5 stars",
"points": 9.8,
"status": "partial",
"details": [
{
"code": "stars",
"params": {
"count": 5
}
}
],
"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": "2 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 2
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "moderate",
"name": "Community health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "at_risk",
"name": "Sustainability & Governance",
"value": 48,
"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": "excellent",
"name": "Issue & PR responsiveness",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"merged_prs": 15,
"open_issues": 0,
"closed_issues": 1,
"issue_closed_ratio": 1,
"closed_unmerged_prs": 0
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "100% of issues closed",
"points": 46.8,
"status": "met",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 100
}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "15/15 decided PRs merged",
"points": 38.2,
"status": "met",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 15,
"decided": 15
}
}
],
"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": 55,
"inputs": {
"followers": 42,
"owner_type": "User",
"is_verified": null,
"owner_login": "jhuntwork",
"public_repos": 23,
"account_age_days": 5957
},
"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": "42 followers of jhuntwork",
"points": 11.7,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 42,
"login": "jhuntwork"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "23 public repos, account ~16 yr old",
"points": 22.1,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 23
}
},
{
"code": "account_age_years",
"params": {
"years": 16
}
}
],
"max_points": 25
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "moderate",
"name": "Engineering Quality",
"value": 54,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "at_risk",
"name": "Engineering practices",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 30,
"inputs": {
"has_ci": false,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "excellent",
"name": "Documentation",
"note": null,
"notes": [],
"value": 90,
"inputs": {
"topics": [],
"has_wiki": true,
"homepage": "https://codeberg.org/merelinux/mere",
"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": "https://codeberg.org/merelinux/mere",
"points": 15,
"status": "met",
"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": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "at_risk",
"name": "Security",
"value": 37,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "at_risk",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): CI-Tests, Dangerous-Workflow, Packaging, Pinned-Dependencies, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"ci_tests",
"dangerous_workflow",
"packaging",
"pinned_dependencies",
"signed_releases",
"token_permissions"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 37,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 12,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 6,
"scorecard_aggregate": 3.7
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 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 workflows found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "no update tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow not detected",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "no dependencies found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "no SAST tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "No tokens found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "0 existing vulnerabilities detected",
"points": 7.5,
"status": "met",
"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": "at_risk",
"name": "AI Readiness",
"value": 35,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "at_risk",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.99,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "no CLAUDE.md / AGENTS.md / editor rules",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_instructions",
"params": {}
}
],
"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": "99 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 99,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "critical",
"name": "Verify loop (build / test / typecheck)",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_pinned_dependencies"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 24,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [],
"has_dockerfile": false,
"typed_language": false,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [],
"agent_commit_share": 0,
"toolchain_manifests": [],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"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": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "no agent-authored commits among the last 100",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_authored_commits",
"params": {
"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": "no dependencies found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "moderate",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 55,
"inputs": {
"primary_language": "Zig",
"largest_source_bytes": 441,
"source_files_sampled": 1,
"oversized_source_files": 0
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Zig without a type-check config",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_typecheck_config_language",
"params": {
"language": "Zig"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "0/1 source files over 60KB",
"points": 55,
"status": "met",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 1,
"oversized": 0
}
}
],
"max_points": 55
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token"
],
"report_type": "repository",
"generated_at": "2026-07-31T12:17:04.796925Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/j/jhuntwork/mere.svg",
"full_name": "jhuntwork/mere",
"license_state": "standard",
"license_spdx": "MIT"
}