Public record
Software health reportschema 0.27.0 · metrics 1.13.0 · 2026-07-28 21:20 UTC

emmanuel-D / truthboard

Git-native tracker where status is derived from repo reality, never typed. Specs in markdown, boards from git, MCP for AI agents, drift auditing for any repo.

GoMIT★ 0 stars⑂ 0 forkssince Jul 2026View on GitHub ↗

emmanuel-D/truthboard holds a health index of 48 out of 100, placing it in the At risk band. It scores highest on Engineering Quality (71/100) and lowest on Community & Adoption (24/100). It was last updated today. A single contributor accounts for most of its recent work.

48
overall / 100
At risk

Software health index

Metrics are grouped into weighted categories on one standardized 1–100 scale. Overall starts as their weighted mean; when public evidence triggers the High-Risk Jurisdiction Policy, the rating is adjusted and receives an At risk ceiling of 49. AI Readiness sits outside the overall score.

48
Excellent85-100Exemplary; meets essentially all checked criteria
Good70-84Healthy; minor gaps
Moderate50-69Acceptable with notable gaps; review recommended
At risk30-49Significant weaknesses; adoption warrants caution
Critical1-29Severe problems (abandoned, single-maintainer, no hygiene)
VitalityCommunity &AdoptionSustainability &GovernanceEngineeringQualitySecurityAI Readiness

Score profile

Each axis is a category. The shape matters more than the average — a healthy subject fills the whole shape, while a spike-and-crater profile means strength in one dimension is masking risk in another.

Ownership

Emmanuel DademPersonal account
2 followers15 public repossince Mar 2018

This repository is owned by a personal account. A single-owner project carries more continuity risk than an organization-backed one.

Package ecosystems

RegistryPackageVersionDownloads / moVersionsLast publish
Gogithub.com/emmanuel-D/truthboardv0.10.0-160 days ago

Metrics by category

Vitality

Is the project alive — is code being written and are releases shipping?

69Moderate · 22% of overall
How it's scored
36/36Push recency — last push 0 days ago
0.7/36Commit cadence — 1/52 weeks with commits
18/18Commit volume — 172 commits in the last year
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Inputs used
commits_last_year172
human_commit_share1
days_since_last_push0
active_weeks_last_year1
How it's scored
27/27Ships releases — 16 releases published
36/36Release recency — latest release 0 days ago
27/27Release cadence — a release every ~1 days
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Inputs used
releases_count16
latest_release_tagv0.10.0
releases_from_tagsno
days_since_latest_release0
mean_days_between_releases1

Community & Adoption

Does the project have users, downloads, attention, and a welcoming setup for contributors?

24Critical · 18% of overall
How it's scored
0/60Stars — 0 stars
0/25Forks — 0 forks
0/15Watchers — 0 watchers
Inputs used
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
How it's scored
22.5/22.5README
22.5/22.5License — recognized license (MIT)
0/18CONTRIBUTING guide
0/13.5Code of conduct
0/7.2Issue template
0/6.3PR template
Inputs used
has_readmeyes
has_licenseyes
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

Sustainability & Governance

Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?

43At risk · 24% of overall
How it's scored
9/54Bus factor — 1 contributor(s) cover half of all commits
0/22.5Commit distribution — top contributor authored 100% of commits
1.4/13.5Contributor breadth — 1 contributors
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Inputs used
bus_factor1
contributors_sampled1
top_contributor_share1
How it's scored
0/46.8Issue resolution — 0% of issues closed
38.2/38.3PR acceptance — 1/1 decided PRs merged
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Inputs used
merged_prs1
open_issues1
closed_issues0
issue_closed_ratio0
closed_unmerged_prs0
How it's scored
10/30Ownership backing — personal (user) account
0/20Verified domain — not applicable to user accounts
3.4/25Owner reach — 2 followers of emmanuel-D
20.8/25Track record — 15 public repos, account ~8 yr old
Inputs used
followers2
owner_typeUser
is_verified
owner_loginemmanuel-D
public_repos15
account_age_days3,060
Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.
How it's scored
25/25Published & resolvable — 1 package(s) on go
35/35Publish recency — latest publish 0 days ago
20/20Version history — 16 published versions
20/20Not deprecated — active, not deprecated or yanked
Inputs used
packagesgithub.com/emmanuel-D/truthboard
ecosystemsgo
any_deprecatedno
min_days_since_publish0

Engineering Quality

Are baseline engineering and documentation practices in place?

71Good · 20% of overall
How it's scored
24/24CI workflows — 3 workflow(s)
24/24Tests present
0/16Linter config
0/9.6Pre-commit hooks
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 1 out of 1 merged PRs checked by a CI test -- score normalized to 10
Inputs used
has_ciyes
has_testsyes
has_editorconfigno
has_linter_configno
has_precommit_configno
How it's scored
30/30README
25/25Documentation directory
0/15Documentation / homepage site
10/10Repository description
10/10Topics — 7 topics
0/10Wiki
Inputs used
topicsai-agents, developer-tools, git, golang, kanban, mcp, project-management
has_wikino
homepage
has_readmeyes
has_docs_diryes
has_descriptionyes

Security

Are visible security and supply-chain practices strong, without unresolved high-risk jurisdiction exposure?

28Critical · 16% of overall
How it's scored
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2.5/2.5CI-Tests — 1 out of 1 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5License — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — no data
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
6/7.5Vulnerabilities — 2 existing vulnerabilities detected
Inputs used
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate2.9
Excluded from scoring (no data or not applicable): packaging. Remaining weights renormalized.

AI Readiness

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.

67Moderate · 0% of overall
How it's scored
45/45Agent instructions — AGENTS.md, CLAUDE.md
0/15Machine-readable docs (llms.txt)
29.9/40Legible commit history — 56 of 100 human commits state their intent (structured subject or explanatory body)
Inputs used
has_llms_txtno
legible_history_share0.56
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes1,271
How it's scored
12.6/18One-command bootstrap — go.mod (toolchain convention, no task runner)
22/22Automated tests
0/11Lint / format config
11/11Static type checking — Go (statically typed)
10/10Reproducible environment — Dockerfile, lockfile
10/10Demonstrated agent practice — 25 of the last 100 commits agent-authored or agent-credited
0/8Automated maintenance — no automated dependency updates observed
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Inputs used
has_nixno
has_testsyes
lockfilesgo.sum
has_dockerfileyes
typed_languageyes
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configs
agent_commit_share0.25
toolchain_manifestsgo.mod
dependency_bot_commit_share0
How it's scored
45/45Type-checkable code — Go (statically typed)
55/55Manageable file sizes — 0/71 source files over 60KB
Inputs used
primary_languageGo
largest_source_bytes42,697
source_files_sampled71
oversized_source_files0
How it's scored
0/40API schema (OpenAPI/GraphQL/proto)
20/20MCP server
0/40Runnable examples
Inputs used
example_dirs
has_mcp_signalyes
api_schema_files

Key facts

0GitHub stars
1contributors
172commits, last 12 months
0days since last push
16releases
1bus factor
1open issues
Gopackage ecosystems

Data collection warnings

  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

More detail

OpenSSF Scorecard 2.9 / 10
2.9aggregate

Independent, tool-agnostic security assessment from the open-source OpenSSF Scorecard. Each check rewards a security practice, not a specific vendor's tool. Checks Scorecard could not determine are marked n/a and excluded from the security score (never counted as zero).Scorecard v5.5.0 · 2026-07-28 21:20 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
10CI-Tests1 out of 1 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
n/aPackagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
8Vulnerabilities2 existing vulnerabilities detected
Direct dependencies 3
RegistryPackageVersion constraintManifest
Gogithub.com/charmbracelet/bubbleteav1.3.10go.mod
Gogithub.com/charmbracelet/lipglossv1.1.0go.mod
Gogopkg.in/yaml.v3v3.0.1go.mod
All dependencies not collected

The resolved dependency set could not be collected for this report: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Raw JSON report machine-readable
{
  "data": {
    "repo": {
      "topics": [
        "ai-agents",
        "developer-tools",
        "git",
        "golang",
        "kanban",
        "mcp",
        "project-management"
      ],
      "is_fork": false,
      "size_kb": 704,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Go": 460634,
        "CSS": 18245,
        "HTML": 6616,
        "Shell": 4748,
        "Python": 11579,
        "Dockerfile": 1369,
        "JavaScript": 42697
      },
      "pushed_at": "2026-07-28T14:48:59Z",
      "created_at": "2026-07-15T19:26:57Z",
      "owner_type": "User",
      "updated_at": "2026-07-28T14:55:08Z",
      "description": "Git-native tracker where status is derived from repo reality, never typed. Specs in markdown, boards from git, MCP for AI agents, drift auditing for any repo.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": "https://www.linkedin.com/in/emmanuel-dadem-3b3096209/",
      "name": "Emmanuel Dadem",
      "type": "User",
      "login": "emmanuel-D",
      "company": null,
      "location": "Nuremberg",
      "followers": 2,
      "avatar_url": "https://avatars.githubusercontent.com/u/37305687?v=4",
      "created_at": "2018-03-12T16:52:12Z",
      "is_verified": null,
      "public_repos": 15,
      "account_age_days": 3060
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.10.0",
          "kind": "minor",
          "published_at": "2026-07-28T04:40:23Z"
        },
        {
          "tag": "v0.9.1",
          "kind": "patch",
          "published_at": "2026-07-20T12:25:24Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2026-07-20T11:15:41Z"
        },
        {
          "tag": "v0.8.4",
          "kind": "patch",
          "published_at": "2026-07-20T10:12:20Z"
        },
        {
          "tag": "v0.8.3",
          "kind": "patch",
          "published_at": "2026-07-20T09:43:46Z"
        },
        {
          "tag": "v0.8.2",
          "kind": "patch",
          "published_at": "2026-07-20T09:05:43Z"
        },
        {
          "tag": "v0.8.1",
          "kind": "patch",
          "published_at": "2026-07-20T08:38:24Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-07-19T20:31:34Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-07-19T15:47:49Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-07-18T19:12:23Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-07-18T17:39:12Z"
        },
        {
          "tag": "v0.4.1",
          "kind": "patch",
          "published_at": "2026-07-17T14:36:35Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-07-17T13:36:23Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-07-17T12:52:38Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-07-16T14:37:50Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-07-16T08:11:55Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "2fa8249ceced93fb7425007889ad728fe2dcd845",
          "body": "The MCP server is the one command whose working directory the user does\nnot choose — the client spawns it. It is also the only one that ignores\na repo argument, so a hub whose .truthboard/ sits in a subdirectory can\nonly be served by a shell wrapper that cds first, with an absolute path\nbaked into an otherwise portable .mcp.json.\n\nFound wiring the LetTalk hub so agents launch from the workspace parent.\n\nNo trailers — this is intent.\n\nCo-Authored-By: Claude Opus 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Story: truthboard mcp serves the directory you point it at",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T14:44:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "64d90545d1bc1fdd5d1ea623174c3c884ca031f6",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'fix/tb-71c5-ci-identity'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T04:37:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3be7a46c41e594293e125c5f258749ba1d574e02",
          "body": "CI has been red since tb-71c5 merged, and I did not notice because I\nonly ran the suite on a machine that has a global git identity.\noriginAndClone configured user.name/user.email on the seed repo but not\non the clone, and the delete tests are the first to commit into the\nclone. A CI runner has no c\n[…]\nvisible — red CI flips a\ndone story to regressed — and it did not, because the local board runs\nwithout --forge and never asked GitHub. Worth remembering before\ntrusting a green column.\n\nSpec: tb-71c5",
          "is_bot": false,
          "headline": "Give the board clone a git identity in the test fixture",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T04:37:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "13760ece4407e0516ba9b44e3b92b8eccf2709c9",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-e8e3-repo-chips'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T04:28:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e41fb0d41cc6edd3dc0ae3fc3b6b89663981c3a6",
          "body": "The multi-select was the wrong control and measurably so. Clicked\nthrough in a browser with [hub, server] selected, one unmodified click\non a third option left [connect] alone — two repos dropped, silently, on\nthe field that decides what done requires. The safe gesture was\n⌘-click, the default gestu\n[…]\n\"dropdown\"; the goal was picking from what exists. Intent\nupdated to match what the click test showed, which is the tool working\nas intended — the promise is editable, the proof is not.\n\nSpec: tb-e8e3",
          "is_bot": false,
          "headline": "Repos are toggle chips, not a multi-select",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T04:28:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2efd8e1677e036b0571f56b4ae70eb0598a79fd3",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-5266-redact-credentials'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T04:04:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ce18b657f3f30dd1eda5b025d97e9a2b9d119ee0",
          "body": "A shared board publishes its sync errors — the page prints them as\n\"⚠ remote sync failing: …\" and the header carries them to anyone who can\nload the URL. A spoke clone takes its remote as a command argument, so a\nmanifest with a token in it (which the docs forbid and a hurried\noperator writes anyway\n[…]\ngit's own output —\ngit sanitizes most of what it prints, and \"most\" is not a property worth\nbetting a token on.\n\nHost and path survive redaction. An error naming no remote helps nobody.\n\nSpec: tb-5266",
          "is_bot": false,
          "headline": "Redact credentials where git output is born",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T04:03:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "68cbfdf4277ead4a4d067d62dee2e1cf79f92efb",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-28b0-hub-recipe'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T03:55:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9cfed87aa260dae57cd2f4ce228db708b725079b",
          "body": "The pieces were all documented and the way they compose was not. Arming\nthe edit token is what forces a second credential — the board only reads\na spoke but writes the hub, so the hub needs push and the spokes must\nnot have it, which turns one rewrite rule into two. Nothing said so, and\nfinding out \n[…]\nway to see which credential actually resolves.\n\nAlso covers the step people finish without: a shared board authenticates\nwrites, never reads, so the edit token does not keep anyone out.\n\nSpec: tb-28b0",
          "is_bot": false,
          "headline": "Write down the hub-with-editing deploy, end to end",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T03:52:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9c6ed7c1ff2cf728bcad1210f6e6da7f425f2779",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-c469-ui-feedback'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T03:27:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a279f95ccff934bb33038c4f47b95f6c92b85e52",
          "body": "The board did the right thing and said nothing about it. Creating and\nretiring a story both just closed the dialog, which is exactly what a\ncrash looks like. Sign-off confirmed nothing at all. What feedback did\nexist came in three shapes — a button label, a hint line, a note beside\na field — so ther\n[…]\nays it is reading the repository instead of showing\nempty columns, and says so with the reason if the first audit fails —\nuntil now an unreadable repo and an empty one looked identical.\n\nSpec: tb-c469",
          "is_bot": false,
          "headline": "Say what just happened, and show it straight away",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T03:27:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4515d161dc1ef34245296b3f3d3b5698ca27c9f0",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-e8e3-repos-dropdown'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T03:19:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4a5feb0c2eb6de6cf07f3893127087db2a3c8410",
          "body": "The Repos field was free text, so a typo produced a story that could\nnever be done — done with repos: declared means the trailer landed in\nevery one of them, and a repo that does not exist never lands anything.\nThe server rejected the typo on save, which is the right answer given\nfar too late. Offer\n[…]\norkspace — known repos: hub,\napi, web\"); deselecting it and picking hub saves and rewrites the file.\nOn a single-repo board the field is absent for both a new story and an\nexisting one.\n\nSpec: tb-e8e3",
          "is_bot": false,
          "headline": "Repos is a dropdown of repos that exist",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T03:19:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2195e3e073cfe99fabdadabe9665e1fd423a6eaf",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-71c5-delete-stories'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T03:11:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8294781c0d4e3d23ac042b5b38b136d83fa8b000",
          "body": "There was no delete route at all: the write guard admitted POST\n/api/specs and PUT /api/specs/ and nothing else, so clearing a story\ncreated by mistake meant deleting the file from a clone and pushing by\nhand. That is literally what a probe story on the live lettalk board\ntook to remove.\n\nDELETE /ap\n[…]\none sets to say where a story stands is a status, and statuses are\nderived. The deletion is a commit, so the undo is git revert — which the\nconfirm dialog and the API response both say.\n\nSpec: tb-71c5",
          "is_bot": false,
          "headline": "Retire a story from the board, not from a clone",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T03:11:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5e4d4b087492e5ebeb4420a7e2a57654a45b1136",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-fb2b-sync-latency'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T02:51:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b802badf6399fb1441b619e115554c3496aebd5b",
          "body": "Linking ran `git log --grep <trailer>` for every spec against every\nbranch. On this repo — 68 specs, 17 refs — that was 940 git processes\nfor a single audit, fifteen seconds during which boardCache.get holds\nits mutex while browsers poll every three seconds. That is the \"audit\nunavailable — retrying\n[…]\nfrom the forge unless --no-forge, and those\nAPI calls dominated the wall clock. The numbers above exclude it, which\nalso matches the board, since boardCache only enriches under --forge.\n\nSpec: tb-fb2b",
          "is_bot": false,
          "headline": "Ask git once per branch, not once per spec per branch",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T02:51:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "af420cfeb9ea2602182aed0312f36c9559fb3f32",
          "body": "Saving a story rebased on origin unconditionally before pushing, so\nevery save cost two round-trips to the forge — and the first one bought\nnothing almost every time, because the board is usually the only writer\nand the sync loop has already fetched within its interval. Push first\nand let the remote\n[…]\nis durability,\nnot visibility.\n\nAnd the save button says \"saving…\" and refuses a second press. A save\ntakes as long as the network does, and silence for that whole time\nreads as a hang.\n\nSpec: tb-fb2b",
          "is_bot": false,
          "headline": "Stop paying a forge round-trip for a rebase that does nothing",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T02:06:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a9922f5c869627be5d5fbcb879454a0dc4392ad9",
          "body": "Both were a title and a sentence. Traced the actual paths and wrote\ndown what each one turns on: for deletion, what it means when proof\nalready exists; for sync, which part is a bug and which is a deliberate\ntrade. No trailers — this is intent.",
          "is_bot": false,
          "headline": "Flesh out story deletion (tb-71c5) and sync latency (tb-fb2b)",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T01:36:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "45852b1feb78f2983f8ac0b5b1ff1fd27d9339ce",
          "body": "…, sync\n\nWritten through the shared board before it had push credentials, so\nthey never left the working tree. No trailers — this is intent.",
          "is_bot": false,
          "headline": "Stories drafted from the board: deletion, repos dropdown, UI feedback…",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T01:33:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "912e4ab1a9bb3cac4f1192fc07fa3bbd891c03c3",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-26f5-preflight'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T01:07:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "18e6cf84f4372b69d12ed1cf51832fcf8ebee325",
          "body": "A board on a platform that restarts crashed containers turned every\ncredential problem into the same git error printed once per restart,\nwith the cause buried in it. Five redeploys of a private multi-repo hub\nwent that way, and none of the failures were things git could explain:\na forge answers a mi\n[…]\n carries\non: a hub with an unreachable spoke still serves real truth about the\nrest, and refusing to boot would trade a degraded board for no board.\nSilent when everything is reachable.\n\nSpec: tb-26f5",
          "is_bot": false,
          "headline": "Prove the deploy can reach its remotes before serving",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T01:07:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8d8790be7ba07d68c66876a0359b24b7243eead3",
          "body": "Three stories from deploying a private multi-repo hub on Coolify:\npreflight reachability checks (tb-26f5), credential redaction in logs\n(tb-5266), and a complete private-hub-with-editing recipe (tb-28b0).\nNo trailers — this is intent, not proof.",
          "is_bot": false,
          "headline": "Deploy hardening backlog from the lettalk hub rollout",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T00:57:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "264700604b404aefa162ac8d4806ba13d6b91cc2",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-fd0b-build-git-config'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T00:23:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e26a4b6354fa65229a79321b93174beb3be0f5fa",
          "body": "Deploy platforms turn every configured environment variable into a\nbuild ARG, so a private hub's runtime credential is present during the\nimage build. Git validates the whole GIT_CONFIG_COUNT set on every\ninvocation, so a single missing VALUE_n failed `git config --system\nsafe.directory` in the runt\n[…]\nng at `apk add`, nowhere near the credential that caused it.\n\nPin that call to GIT_CONFIG_COUNT=0. A credential typo now fails the\nclone it belongs to, with a message about credentials.\n\nSpec: tb-fd0b",
          "is_bot": false,
          "headline": "Build-time git ignores injected GIT_CONFIG_*",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-28T00:23:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b7aa847178b99153674c97ba56d434ecddf373c2",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-0ac4-webhook-race'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T12:20:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0b9435502095ca47d84b5be3f8d4f93e0f727e96",
          "body": "A webhook kick ran `go trigger()` and nothing could observe it. The\ngoroutine runs git inside the repository, so a caller tearing that\nrepository down — a test's t.TempDir(), a server shutting down — raced a\nrefresh mid-write. CI caught it once as \"unlinkat .../.git: directory\nnot empty\".\n\nHandler n\n[…]\nitsWebhookRefresh asserts Wait\ndoes not return while a refresh is in flight, and fails when Wait is\nstubbed out. Under -race it also establishes the happens-before that a\ncleanup needs.\n\nSpec: tb-0ac4",
          "is_bot": false,
          "headline": "The webhook refresh can be awaited",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T12:20:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2ebf868b5838e47181557c24d9248c83665239a3",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-deploy-private-hubs'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T12:05:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2f26be712641f056bc368cdeb8fa24111d8363c2",
          "body": "Deploying a real private hub to Coolify hit two gaps the docs set the\nreader up for.\n\nREPO_URL with an embedded token is documented, so private repos look\nhandled. For a hub they are not: spokes are cloned from the remotes in\nthe committed workspace.yml, which must never carry a credential, so the\nh\n[…]\nnot buried later, with the mitigations named.\n\nAlso documents the first-boot window where spokes read as unreadable\nwhile their mirrors clone, so it is not mistaken for a failed deploy.\n\nSpec: tb-c847",
          "is_bot": false,
          "headline": "Deploy docs cover private multi-repo hubs and read exposure",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T12:05:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dbaf86914594c537bca4bfdca93509d7b2715d13",
          "body": "Verify the Docker image on a real engine",
          "is_bot": false,
          "headline": "Merge pull request #2 from emmanuel-D/feature/tb-c4c3-docker-verified",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T11:45:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "097909a65e5913996dbcde4784f226200623a5e6",
          "body": "Backlog intent only — no Spec: trailer, which on main would derive the\nstory done the moment it is written.",
          "is_bot": false,
          "headline": "Story: the webhook test races its own background refresh",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T11:43:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7b751f39b237e7b5072e7a10f81a12cfae408193",
          "body": "The smoke test failed exactly as intended with a wrong expected version,\nso its assertions are not vacuous. Restoring the real expectation.\n\nSpec: tb-c4c3",
          "is_bot": false,
          "headline": "Revert the negative control",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T11:41:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8ae0930368fadddd2f705eb4909d5a58941575eb",
          "body": "Spec: tb-c4c3",
          "is_bot": false,
          "headline": "TEMP negative control: prove the smoke test can fail",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T11:39:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c092123f392ba25bf47e05ddd336ac41adeb29a2",
          "body": "The Dockerfile and entrypoint shipped in tb-146e were checked by\ncross-compiling the build line and driving the entrypoint directly; no\ndocker build had ever run, because the author's machine has no Docker\nengine. That made \"the image works\" an assumption in the one place\nusers are told to deploy fr\n[…]\n case exiting\nnon-zero with its actionable message. It runs in CI and is the same\ncommand anyone with Docker can run by hand — which is the point, since\nthis repo cannot run it locally.\n\nSpec: tb-c4c3",
          "is_bot": false,
          "headline": "Verify the Docker image on a real engine",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T11:37:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3b4b3ecb2fe321ea700251bf1546e7b5132bc067",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-1eb5-spoke-identity'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T10:42:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7ab38f8bf3fb5c05ddcd40f8bf0df49ba613885",
          "body": "Resolve accepted a declared path on the sole evidence that the directory\nexisted. A mistyped or stale path therefore made the board gather proof\nfrom the wrong repository and report it with full confidence — the only\nsilent wrong answer in a tool whose entire claim is that its findings are\ntrustwort\n[…]\n\nVerified end to end on a hub pointed at the wrong one of two similarly\nnamed checkouts: refused in the audit and carried to the board as\nworkspace health, naming both URLs and the fix.\n\nSpec: tb-1eb5",
          "is_bot": false,
          "headline": "A declared spoke path must prove it is the declared repo",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T10:42:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a82488deee072e8e76a6df1d55c9ecf71a1248ff",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-ad3f-status-version'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T10:30:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e74923275f6ce978a6bf82ff666940872bdb1c2b",
          "body": "A detached board keeps the binary it started with, so an install or a\nbrew upgrade silently leaves it serving old code — and the binary it\nstarted from is usually gone by then, so `ps` cannot tell you either.\nIt bit three times in one day; each time it was found by reading ps.\n\nstatus now asks the b\n[…]\ns both versions without implying a direction: a dev\nbuild asking about a release board is as common as the reverse, and the\nfirst wording claimed the board was behind when it was ahead.\n\nSpec: tb-ad3f",
          "is_bot": false,
          "headline": "truthboard status reports the serving version",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T10:30:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "259f7b3bb9907581a9ca7660d4f74a9a797d37e1",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-569e-version-from-buildinfo'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T10:05:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6b9f9eac23f0ebf20256fc58906c79ed836b5fd5",
          "body": "Release binaries are stamped by -ldflags; go install applies none, so the\ninstall path most likely to be used by Go developers produced a binary\ncalling itself \"dev\" — and selfupdate refuses to replace those, quietly\nopting those users out of updates.\n\nThe version now falls back to the module versio\n[…]\nunity.\n\nThe literal initialiser on `version` is load-bearing: -X only rewrites a\nvariable initialised to a constant, so the fallback runs in init() rather\nthan becoming a function call.\n\nSpec: tb-569e",
          "is_bot": false,
          "headline": "go install builds report their module version",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T10:03:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "439a3a04fae7a3e5769c6614459bc43d57bcaa82",
          "body": "Backlog intent only — no Spec: trailer, which on main would derive the\nstory done the moment it is written.",
          "is_bot": false,
          "headline": "Story: go install builds report their module version, not dev",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T09:58:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3e4f36cc80aee233f3d29186d556b1308c4baa00",
          "body": "Generalise the three specs that cited a client's private repo layout as\nevidence — the bugs they describe are unchanged, only the names go — and\ndrop the README caveat about unauthenticated install paths 404ing, which\nstops being true the moment the repo is public.\n\nSpec: tb-9693",
          "is_bot": false,
          "headline": "Prepare for the public flip",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T09:52:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4242902455266ce206ec95105ac7ed4ab8440eb7",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-d146-hook-upgrade'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T09:39:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1f95974b67830f45b0341809c7764b59a2163b32",
          "body": "installHook returned \"already installed\" on seeing hookMark and never\ntouched the text again, so a hook was frozen at whatever version wrote\nit — which meant tb-3d43's quieter nudge could not reach a single\nexisting adopter.\n\nThe nudge now closes with hookEndMark, so future versions can bound\ntheir \n[…]\nm's lines survived on both sides, a re-run left\nthe file untouched, and the upgraded nudge is silent on intent-only\ncommits.\n\nAlso gofmt internal/audit/audit_test.go, missed in tb-3d43.\n\nSpec: tb-d146",
          "is_bot": false,
          "headline": "Re-running init upgrades an existing commit-msg hook",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T09:39:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "48453b3b2741c32f08590c393734e86e67eb17f3",
          "body": "Backlog intent only — no Spec: trailer, which on main would derive the\nstory done the moment it is written.",
          "is_bot": false,
          "headline": "Story: re-running init upgrades an existing commit-msg hook",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T09:14:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7f03a5bc23c73fbac2f90b414c484ff68b504366",
          "body": "Backlog intent only — no Spec: trailer, which on main would derive the\nstory done the moment it is written.",
          "is_bot": false,
          "headline": "Story: truthboard status reports the serving version",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T09:12:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "35c77ac6028bb3bd6acb53997bdc747a21f9b460",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-3d43-hook-agrees'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T09:00:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bd80ff14c954e2b2dd3d8c040108d517d88121de",
          "body": "The commit-msg nudge warned \"this commit will show up as shadow work\"\non spec-only commits that the audit exempts — caught landing the tb-1eb5\nstory. A hook that cries wolf on the one commit shape it should ignore\nteaches you to ignore the hook.\n\nThe nudge now reads the staged fileset and applies the same governed rule\nas audit.governedFile. Silence is the exception, not the fallback: an\nempty or unreadable staged list falls through to the warning.\n\nSpec: tb-3d43",
          "is_bot": false,
          "headline": "The trailer hook agrees with the audit on intent commits",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T09:00:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "07163c3294d606b7fabc2157577c02cc9687cd80",
          "body": "Backlog intent only, no trailer — a Spec: trailer on main would derive\nthis story done the moment it is written.",
          "is_bot": false,
          "headline": "Story: a declared spoke path must prove it is the declared repo",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T08:57:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "623c7f9022d1345d633371ab0ab0c6bfd881c319",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-3d43-adoption-not-shadow'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T08:55:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ee387998a7f57202ddba82683ecf524b79449dc",
          "body": "Installing truthboard on the LetTalk hub for real showed the board's\nopening statement accusing its own setup of drift: the adoption commit\nlands directly on the integration branch by necessity — there is no\nboard to open an MR against yet — and tb-6e13's exemption only covered\n.truthboard/, so the \n[…]\nDE.md. Confined to those, a\ncommit changes how work is tracked and never the product. Mixed commits\nstay shadow work — code smuggled in beside intent is the case the\nfinding exists for.\n\nSpec: tb-3d43",
          "is_bot": false,
          "headline": "The adoption commit is not shadow work",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T08:55:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "042e5043d433a623de146b67d72d9293df0e35f5",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-a4ab-init-git-doctor'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T08:32:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8400299aaedb52516907346ec847df826d62762b",
          "body": "A clean-room run of the LetTalk hub setup on the released v0.8.0 binary\nfound the last onboarding hole. Single repos are already git repos when\nyou adopt them; a multi-repo hub is the one repo people create as an\nempty directory by hand, and init --workspace scaffolded it in silence,\nthen closed wit\n[…]\ninted the name of an internal for-each-ref invocation\n— so gitrepo.Run translates \"not a git repository\" into the directory\nand the fix, leaving every other failure its command context.\n\nSpec: tb-a4ab",
          "is_bot": false,
          "headline": "Init reports a hub that is not a git repository yet",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-20T08:32:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cf6878be560b6c2626002b9c2c36295d38adae21",
          "body": "Spec: tb-9693",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-9693-install-ergonomics'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T20:20:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7ab68009b0b98b7e45070a4adc93c3d1aa83ee9",
          "body": "install.sh (repo root, POSIX sh, shellcheck-clean): resolves the current\ntag from the releases/latest redirect — the same never-stale pattern as\ndeploy.md — picks darwin/linux × amd64/arm64, verifies the tarball against\nchecksums.txt (sha256sum or shasum), and installs to /usr/local/bin when\nwritabl\n[…]\na shellcheck job over all shipped shell.\n\nREADME leads with curl|sh and brew, keeping tarballs and go install as\nalternatives, with a note that unauthenticated paths 404 until the flip.\n\nSpec: tb-9693",
          "is_bot": false,
          "headline": "Install ergonomics, staged for the public flip: install.sh + brew tap",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T20:20:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9c7d5b217f6defaf9ee61fe5aa12bf2e8d5c7155",
          "body": "Spec: tb-dcef",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-dcef-repo-filters'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T20:11:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "43639e3e311388cf1a31a927468a510ac638fffa",
          "body": "…cycle\n\nOne membership rule everywhere: a story belongs to a repo through declared\nrepos: intent, a per_repo landing entry, a linked branch living there\n(label prefix; unprefixed = hub), or the landing itself — so a repos:\nstory appears under every repo it declares and a plain story under the\nrepos \n[…]\nes → off, shown as repo= in the header like the\nother filters; the key and its footer hint exist only when a workspace\ndoes. Single-repo boards render byte-identically in both surfaces.\n\nSpec: tb-dcef",
          "is_bot": false,
          "headline": "Workspace board gets a repo dimension: filter chips, meta links, TUI …",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T20:11:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7d90920efa515a547bbff045e785e27adaa4d052",
          "body": "Spec: tb-9aa1",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-9aa1-init-workspace'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T19:59:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d801491c4917d108e8b797e8b2afb2ea3fd95269",
          "body": "init gains --workspace name=remote pairs (plus repeatable --path name=dir\nfor local spokes, alone or annotating a pair): workspace.Declare validates\nthe whole batch first — name grammar and the reserved hub name via the\nsame ValidName the loader enforces, duplicates, remote-or-path — and only\nthen w\n[…]\ned spoke and documents that\nspokes stay loud unreadable findings until a path exists or the board\nserver clones them. docs/multi-repo.md quick start now leads with the\none-command path.\n\nSpec: tb-9aa1",
          "is_bot": false,
          "headline": "truthboard init --workspace: scaffold a multi-repo hub in one command",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T19:59:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "909418d61461aa5d8e91e4fdc95f1a0633fe64c7",
          "body": "Spec: tb-711f",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-711f-forge-per-spoke'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T19:49:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e1f18bdf850408a8813626f751c2ccba88f321c7",
          "body": "…repo\n\nThe hub-only guard falls: EnrichWithForges fetches forge data per repo —\nthe hub first, then every readable spoke, each repo's own remote deciding\nwhich forge (gh/glab) answers. A spoke branch with an open PR now derives\nin-review, claims-vs-proof runs against each spoke's own tracker with\nsu\n[…]\n\nevery forge that answered, not just the hub's — spoke-only claims were\notherwise computed but never rendered.\n\nSpec scope widened to the callers and renderers this necessarily touches.\n\nSpec: tb-711f",
          "is_bot": false,
          "headline": "Forge enrichment per spoke: PRs, claims, and CI from every workspace …",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T19:49:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2f9adc5327abae9be82894197c3b64c533ddbaef",
          "body": "Five stories for review, ids bare on purpose (a Spec: trailer on main\nwould derive them done): forge enrichment per spoke (tb-711f) and\nworkspace board repo filters (tb-dcef) extend the multi-repo epic;\ninit --workspace scaffolding (tb-9aa1) closes the hub-setup DX gap;\nDocker end-to-end verificatio\n[…]\nublic-flip install\nergonomics — install.sh + brew tap (tb-9693) — round out ship\nreadiness. Priorities are a proposal: reorder or delete freely.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Backlog: next phase after the multi-repo release",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T15:48:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7c677739fb6c18663100434dbfb47705399297e3",
          "body": "Spec: tb-9cf1\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-9cf1-docs-version-proof'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T15:42:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8d2c43db9d55057c61786dbcf2e2f65c787b1aee",
          "body": "deploy.md's install one-liner named the v0.5.0 tarball — stale since\nv0.6.0, and a staleness class, not an instance: any hardcoded tag dies\non the next release. The snippet now resolves the current tag from the\nreleases/latest redirect at run time (verified against a public repo's\nredirect; the gh r\n[…]\nts — extracted binary reports\ntruthboard v0.6.0). README Status: v0.6.0 with multi-repo workspaces\non main awaiting the next tag.\n\nSpec: tb-9cf1\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Docs catch up with reality: version-proof install line, README status",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T15:42:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "26baac21ebcbe8e274ad1793b77c2ac92a716a4a",
          "body": "Spec: tb-f515\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-f515-agent-decomposition'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T15:22:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8f470c218c81d90589da3eaaca174384e226312e",
          "body": "repos: (tb-c512) is the mechanism; per-repo decomposition is the\npractice, and the agent picking up a fat story is the one who should do\nit — never the PO on a phone. The adoption agreement gains a multi-repo\nsection when the hub carries a workspace manifest: split the story\n(narrow the original int\n[…]\n contract\nwith per-repo evidence, MCP flow test drives narrow + create-child +\nunknown-repo rejection + next ordering end to end.\n\nSpec: tb-f515\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Agents decompose cross-repo stories into per-repo children",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T15:22:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3028a9df590b9b7e692b5273cea6af8ce6e1a432",
          "body": "Spec: tb-c512\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-c512-cross-repo-done-semantics'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T15:10:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "eef92848a0eb3e4b6694addd4e16566d1a3d3363",
          "body": "Git cannot prove the absence of work it never knew was intended, so a\nstory that must land in several repos now declares it: repos: [api,\nweb] in frontmatter (\"hub\" is reserved for the repo carrying\n.truthboard/ — the manifest refuses a spoke by that name). With repos:\ndeclared, done requires the tr\n[…]\nond landing, 400 on unknown\nrepos over the API, detail-view Repos row and editor round-trip in\nChrome with no new console errors.\n\nSpec: tb-c512\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Cross-repo done semantics: repos as intent, per-repo evidence",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T15:10:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a1f1ed1d4ecfa07537b4d465ef59dd1acf78d252",
          "body": "Spec: tb-8a79\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-8a79-multi-repo-workspace'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T14:50:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8b75194c8898c3eeb104fb8879058c4ecda40b85",
          "body": "Hub-and-spokes: intent stays in the hub repo's .truthboard/, proof is\ngathered from every spoke declared in .truthboard/workspace.yml. The\naudit fans out over hub + resolvable spokes — units, digest, and shadow\nwork carry a repo tag; spec linking, landing, and revert detection run\nper repo with evid\n[…]\npath checkout +\nremote-only spoke), CLI audit, live board with self-healed mirror\nclone, browser render with zero console errors.\n\nSpec: tb-8a79\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Multi-repo workspace: one board over N repositories",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-19T14:50:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f71130bd5438597f7751aabaf10ee7ea5eb413fc",
          "body": "One board over N repositories, phased: workspace manifest with merged\naudit (tb-8a79), repos: frontmatter for cross-repo done semantics with\nper-repo evidence (tb-c512), agent-side decomposition of fat stories\ninto per-repo children (tb-f515). Intent lives in the hub repo; proof\nis gathered per spok\n[…]\nd, never typed.\n\nIds kept bare above on purpose: a Spec: trailer on main would derive\nthese stories done the moment this commit lands on origin.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Backlog: multi-repo epic — hub intent, workspace proof, cross-repo done",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T19:36:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d5a771b62d1a7e8720654e785441b52c33d14fe8",
          "body": "Spec: tb-6e13",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-6e13-remote-intent-editing'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T19:06:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "addd6f227a3ee36ef0257a63e7e626c24aa8e9b3",
          "body": "…k them up at home\n\nAn edit token (--edit-token / TRUTHBOARD_EDIT_TOKEN) arms intent writes\non a shared board. Reads stay open to anyone; writes carry the token\n(X-Truthboard-Token or bearer, constant-time compared like the webhook\nsecret) and land as real commits: the server adds the one spec file,\n[…]\nome — unlock, create from the browser, commit pushed to origin,\nand truthboard next in a second clone handing back the new story.\n\nSpec: tb-6e13\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Remote intent editing: create stories from a shared board, agents pic…",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T19:06:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bd7a3b1db23b9606f457b8c065795c1965cb58cb",
          "body": "Spec: tb-146e",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-146e-deploy-docs'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T18:49:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "588b834f1a0f9163effdd620016face208e1a87a",
          "body": "The board becomes a one-URL team service on any machine: a multi-stage\nDockerfile (alpine + git runtime, non-root, clone-on-first-start via\nREPO_URL or a mounted clone), and docs/deploy.md walking through the\nthree shapes — binary under systemd on EC2/VPS, Docker, and Coolify —\nplus poll-vs-webhook \n[…]\nd64, and the entrypoint was driven directly —\nREPO_URL clone path, env-driven flags, 200 on reads, 403 on writes\nbeyond loopback.\n\nSpec: tb-146e\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Shared board deploys anywhere: Dockerfile + server install docs",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T18:49:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bfde85d0ebec30f4b9143517e19adab38f6f4ec7",
          "body": "From a phone, create or edit a story on the shared board; the server\ncommits the intent to its clone and pushes to origin, and the agent at\nhome picks it up with truthboard next. Gated on an edit token — until\nthen shared boards stay read-only.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Backlog: remote intent editing from a shared board",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T18:34:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d58dfa91e873971656c843de5a90361a44db599e",
          "body": "Spec: tb-18df",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-18df-mcp-client-docs'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T18:13:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3a0f649940b2467945d48187ed17d2d1fcd5c1e6",
          "body": "The stdio MCP server has nothing Claude-specific in it, but the README\nonly showed the Claude Code registration command, so the question kept\ncoming up. The MCP section now says so outright and carries registration\nsnippets for Cursor, Codex CLI, and Gemini CLI, plus a note that\nAGENTS.md (not CLAUDE.md) is the cross-tool working agreement. The spec\ngets its real goal and acceptance in the same change.\n\nSpec: tb-18df\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Document that the MCP server works with any MCP client",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T18:13:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1b577d334a84015a59f59416764813c0e50006ec",
          "body": "Spec: tb-69d9",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-69d9-readme-v05'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T17:40:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ac764f3d2b5022eeb61bb011d6b49ed39110288",
          "body": "Spec-mode section grows the intent vocabulary (type, points, needs with\nderived waiting, dated sprints); new sections for the terminal board and\nthe explicit LLM draft/review commands; the web board section documents\n--notify transitions and the webhook + SSE live mode, and stops claiming\na single embedded HTML file; MCP tool list completed; Status says v0.5.0\nand points readers at this repo's own live board.\n\nSpec: tb-69d9\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "README documents the v0.5 feature set",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T17:40:14Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "96b1d041caa09aae6e7c1aa1e44db3d9815cd74d",
          "body": "Spec: tb-c56b",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-c56b-dependencies'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T17:35:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ec5f5e65bbbc02b08b7020238d13c1cc7ba8c69e",
          "body": "needs: [tb-xxxx] frontmatter is pure intent, writable via spec new\n--needs, MCP create/update, and the web editor — every write path\nvalidates ids against the specs that exist (before creating the file,\nso a typo never leaves an orphan; the same latent orphan bug in the\ntype validation is fixed by t\n[…]\ned as\nthe chain, and cycle members are never handed out. A need referencing\na vanished id shows as tb-gone? — visible, not fatal.\n\nSpec: tb-c56b\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Spec dependencies: needs as intent, readiness derived",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-18T17:35:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c4b1deaff29c2ede12937372d6822ae8360894d3",
          "body": "Spec: tb-ad46",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-ad46-notifications'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T15:05:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "015f5aca7cedffffe5ae86ac0cd305b8e0941342",
          "body": "ui --notify <url> (env TRUTHBOARD_NOTIFY_URL; detach passes it through\nthe environment — Slack webhook URLs are secrets) arms a notifier on\nthe board process: once a minute, and immediately on a push webhook, it\nre-derives the board, diffs each spec's status against the last check\n(.git/truthboard/n\n[…]\ndence line. First sight is baseline, steady state is silent, and\nwithout --notify nothing changes and no state file ever appears.\n\nSpec: tb-ad46\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Stalled and regressed stories notify someone, not just the board",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T15:05:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c42c0ecdf74a3ae05d4ec9138d9e22a68974d0a1",
          "body": null,
          "is_bot": false,
          "headline": "Backlog: notifications and spec dependencies",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T14:55:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "80531bbd7b1fb5fb87abbd973f9f02123e2103f7",
          "body": "Spec: tb-a8a7",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-a8a7-readme-screenshots'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T14:34:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a6109472644ce23931832d481dd07367d24671db",
          "body": "Two captures from a realistic acme-shop demo (checkout + activation\nepics, sprint s12 mid-flight): the derived kanban with stat tiles,\nfilters, and the dated sprint rollup; and a story detail with signed-off\nGherkin acceptance above the derived-truth panel. Captions spell out\nwhat the pictures argue — statuses computed from branches and merges,\nintent editable, proof not. Images live in docs/screenshots, no\nexternal hosts.\n\nSpec: tb-a8a7\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "README shows the board: screenshots from a demo repo",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T14:34:05Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "21b8967be6f9e497c9b8a137925e3fbd2aceba68",
          "body": "Spec: tb-f82e",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-f82e-dialog-scroll-version'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T14:11:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9cad55a9053c9a00dd6d93c0629b26cf7f36e138",
          "body": "The dialog body capped its height with calc(86vh - 8rem) — a guess at\nheader/footer size that the detail view's chips and assign rows, and\nthe editor's grown field grid, had outgrown, clipping the footer\nbuttons out of reach. Dialogs are now flex columns: chrome keeps its\nsize, the body flexes and s\n[…]\ned. The serving version now also sits next to the page title,\nand source builds say 'dev build (source)' instead of a bare 'dev'.\n\nSpec: tb-f82e\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Board dialogs scroll properly and the serving version is always visible",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T14:11:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "22ddd159e4c2ba400b9ff5c8916a392a513b3664",
          "body": "Spec: tb-40c4",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-40c4-static-split'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T14:08:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "83678c5b608d8e51693d232369572dbd613b8a13",
          "body": "internal/web/static/{index.html,app.css,app.js} embedded as a directory\nand served same-origin under /static/ — organized, diffable, and\nsyntax-checkable, with go build still the entire pipeline. The\nself-containment test now proves the stronger property directly: every\nsrc/href on the page must be same-origin and actually served by the\nhandler, instead of banning asset tags outright.\n\nSpec: tb-40c4\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Split the web page into embedded static assets",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T14:08:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4b8aaf3e2fe7e91d4ef064c3299ac6327aa4557d",
          "body": null,
          "is_bot": false,
          "headline": "Backlog: static-asset split and the dialog/version UI bug",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T13:59:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "344175907eea63dcde4bb6c5ff684dda7236d897",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "CLAUDE.md: carry the Truthboard working agreement into Claude sessions",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T13:34:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ed696e87ffa4c9a3355e8eb8a4358959ff05536b",
          "body": "Spec: tb-f21c",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-f21c-live-shared-board'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T13:25:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "411da51ba012c65a02fbb815ff9247018022a20d",
          "body": "ui --webhook-secret (or TRUTHBOARD_WEBHOOK_SECRET, which detach passes\nthrough the environment, never argv) arms POST /webhook: a forge push\ncarrying the secret — GitLab's X-Gitlab-Token, GitHub's HMAC-SHA256\nbody signature, or ?token= — triggers an immediate coalesced fetch and\nre-derive instead of\n[…]\nard on\npurpose: it carries its own auth and can only make the board fresher —\nspec writes stay forbidden there, verified by test.\n\nSpec: tb-f21c\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Live shared board: webhook-triggered fetch and browser push",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T13:25:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7117e2487a90ffe4bcab71180e25cbafbff7490c",
          "body": "Spec: tb-1be0",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-1be0-embedded-llm'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T13:18:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3a9245ea46f53a4382c4110925f9f56a2805ebf3",
          "body": "internal/llm speaks Anthropic (ANTHROPIC_API_KEY) or a local Ollama\n(OLLAMA_HOST) over plain HTTP — no SDK. truthboard draft turns a\nconcept into an epic of fully-formed stories written through the same\nspec files a human would edit, refusing any story that arrives without\na Goal and Acceptance chec\n[…]\n derived facts — the LLM is a\nwriter, never a source. Nothing calls a model unless one of the two\ncommands is explicitly invoked.\n\nSpec: tb-1be0\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Embedded LLM: draft a backlog, narrate the sprint review",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T13:18:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b5caf08321cbe77560ee6e0de2675f8db029b6b8",
          "body": "Spec: tb-8dd7",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-8dd7-tui-board'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T13:15:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7845823a90f3fc0573b6672e4af1e0300dbf81df",
          "body": "truthboard board opens the derived board in the terminal: kanban\ncolumns (core four always, stalled/regressed only when occupied),\narrow/vim navigation, enter for a detail pane that reads the spec's\ngoal and acceptance from disk, e/s/a cycling filters for epic, sprint,\nand owner, and d/g views for t\n[…]\nrictly\na viewer — there is no keybinding that writes anything, because\nstatuses are derived from git and there is nothing to set.\n\nSpec: tb-8dd7\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Terminal board: a read-only Bubbletea TUI",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T13:15:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "893f389938b00efa637d03cbd4505f19de331778",
          "body": "Spec: tb-fa9b",
          "is_bot": false,
          "headline": "Merge branch 'feature/tb-fa9b-spec-types'",
          "author_name": "Emmanuel Dadem",
          "author_login": "emmanuel-D",
          "committed_at": "2026-07-17T13:06:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 16,
      "commits_last_year": 172,
      "latest_release_at": "2026-07-28T04:40:23Z",
      "latest_release_tag": "v0.10.0",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 1,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 1
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/emmanuel-D/truthboard",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/emmanuel-D/truthboard",
          "is_deprecated": false,
          "latest_version": "v0.10.0",
          "repository_url": "https://github.com/emmanuel-D/truthboard",
          "versions_count": 16,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-28T04:37:41Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 1
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": true,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 42697,
      "source_files_sampled": 71,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 1271
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/charmbracelet/bubbletea",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.3.10"
        },
        {
          "name": "github.com/charmbracelet/lipgloss",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.0"
        },
        {
          "name": "gopkg.in/yaml.v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 1,
        "open_issues": 1,
        "closed_ratio": 0,
        "closed_issues": 0,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "emmanuel-D",
          "commits": 197,
          "avatar_url": "https://avatars.githubusercontent.com/u/37305687?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "release.yml",
        "truthboard.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "1 out of 1 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 8,
            "reason": "2 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "2fa8249ceced93fb7425007889ad728fe2dcd845",
        "ran_at": "2026-07-28T21:20:18Z",
        "aggregate_score": 2.9,
        "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-28T14:49:47Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-20T11:45:32Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 1,
          "created_at": "2026-07-15T19:27:54Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/emmanuel-D/truthboard",
    "host": "github.com",
    "name": "truthboard",
    "owner": "emmanuel-D"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "at_risk",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 48,
      "inputs": {
        "security": 28,
        "vitality": 69,
        "community": 24,
        "governance": 43,
        "engineering": 71
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "moderate",
        "name": "Vitality",
        "value": 69,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "commits_last_year": 172,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 1
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "1/52 weeks with commits",
                "points": 0.7,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "172 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 172
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 16,
              "latest_release_tag": "v0.10.0",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 1
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "16 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 16
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~1 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 1
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 24,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (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": 43,
        "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": "at_risk",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 38,
            "inputs": {
              "merged_prs": 1,
              "open_issues": 1,
              "closed_issues": 0,
              "issue_closed_ratio": 0,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "0% of issues closed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 0
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "1/1 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 1,
                      "decided": 1
                    }
                  }
                ],
                "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": "at_risk",
            "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": 43,
            "inputs": {
              "followers": 2,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "emmanuel-D",
              "public_repos": 15,
              "account_age_days": 3060
            },
            "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": "2 followers of emmanuel-D",
                "points": 3.4,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 2,
                      "login": "emmanuel-D"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "15 public repos, account ~8 yr old",
                "points": 20.8,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 15
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 8
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/emmanuel-D/truthboard"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on go",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "go"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 0 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "16 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 16
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 71,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "3 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "1 out of 1 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [
                "ai-agents",
                "developer-tools",
                "git",
                "golang",
                "kanban",
                "mcp",
                "project-management"
              ],
              "has_wiki": false,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "7 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 7
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "critical",
        "name": "Security",
        "value": 28,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "critical",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Packaging. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "packaging"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 28,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 2.9
            },
            "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": "1 out of 1 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "2 existing vulnerabilities detected",
                "points": 6,
                "status": "partial",
                "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": "moderate",
        "name": "AI Readiness",
        "value": 67,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "good",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.56,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 1271
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "56 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 29.9,
                "status": "partial",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 56,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 66,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.25,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "go.mod (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "go.mod"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile, lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile, lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "25 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 25,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 42697,
              "source_files_sampled": 71,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Go (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/71 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 71,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "critical",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "example_dirs": [],
              "has_mcp_signal": true,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-28T21:20:24.215773Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/e/emmanuel-D/truthboard.svg",
  "full_name": "emmanuel-D/truthboard",
  "license_state": "standard",
  "license_spdx": "MIT"
}

Scores are signals, not warranties. They reflect publicly visible practices on GitHub — not a code audit, and not a security guarantee.

Missing data is excluded and weights renormalized, never scored as zero. Methodology is versioned and open: metrics v1.13.0, schema v0.27.0 — full methodology · metrics wiki.

How one result sits in the wider record: aggregate statisticsGo.