公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-28 05:15 UTC

Obedience-Corp / camp

Workspace and context manager for domain specific AI automation and large scale AI workflows

Go自定义许可证★ 2 星标⑂ 1 复刻始于 2026年1月在 GitHub 上查看 ↗

Obedience-Corp/camp 的健康指数为 100 分中的 57 分,处于「中等」区间。 其得分最高的类别是Vitality(90/100),最低的是Community & Adoption(21/100)。 最近一次更新在今天。 近期的大部分工作由 1 位贡献者完成。

57
总分 / 100
中等

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 49(有风险)的上限。AI 就绪度不计入总体分。

57
优秀85-100堪称典范;基本满足所有检验标准
良好70-84健康;仅有轻微不足
中等50-69可接受,但存在明显不足;建议进行审查
存在风险30-49存在重大薄弱环节;采用时应保持审慎
危急1-29问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

每条轴代表一个类别。形状比平均值更重要——健康的对象会填满整个图形,而“一峰一谷”式画像意味着某一维度的优势正掩盖另一维度的风险。

所有权

6 关注者11 个公开仓库始于 2025年11月

该仓库由组织支持——共同承担、可问责的托管责任,可延续于任何单一维护者之后。

软件包生态系统

注册表软件包版本月下载量版本数最近发布
Gogithub.com/Obedience-Corp/campv0.3.1-301 天前

按类别列示的指标

活力

项目是否仍有生命——是否仍在编写代码,是否仍在发布版本?

90优秀 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 0 天前
19.4/36提交节奏 — 52 周中有 28 周有提交
18/18提交量 — 最近一年 1,960 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year1,960
human_commit_share1
days_since_last_push0
active_weeks_last_year28

发布纪律

100优秀
评分方式
27/27有发布版本 — 已发布 27 个发布版本
36/36发布时效 — 最近一次发布版本于 1 天前
27/27发布节奏 — 约每 2.9 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count27
latest_release_tagv0.3.1
releases_from_tags
days_since_latest_release1
mean_days_between_releases2.9
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

项目是否拥有用户、下载量与关注度,并具备欢迎贡献者参与的配置?

21危急 · 占总体的 18%
评分方式
0/60星标 — 2 个星标
0/25复刻 — 1 个复刻
0/15关注者 — 0 位关注者
所用输入
forks1
stars2
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

44存在风险
评分方式
22.5/22.5README
16.9/22.5许可证 — 存在许可证文件,但不是可识别的许可证
0/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template

可持续性与治理

项目能否在其成员之外延续——巴士系数、响应能力、由谁支持,以及软件包的维护状况?

58中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
2.7/13.5贡献者广度 — 2 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 4 contributing companies or organizations
所用输入
bus_factor1
contributors_sampled2
top_contributor_share0.999
评分方式
38/46.8议题解决 — 81% 的议题已关闭
36.9/38.3PR 接受 — 已裁定的 PR 中 441/457 已合并
4.5/15OpenSSF Scorecard:Code-Review — Found 4/12 approved changesets -- score normalized to 3
所用输入
merged_prs441
open_issues9
closed_issues39
issue_closed_ratio0.812
closed_unmerged_prs16
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
6.1/25所有者影响力 — Obedience-Corp 有 6 位关注者
9.2/25既往记录 — 11 个公开仓库,账户约 0 年
所用输入
followers6
owner_typeOrganization
is_verified
owner_loginObedience-Corp
public_repos11
account_age_days254
评分方式
25/25已发布且可解析 — go 上有 1 个软件包
35/35发布时效 — 最近一次发布于 1 天前
20/20版本历史 — 30 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagesgithub.com/Obedience-Corp/camp
ecosystemsgo
any_deprecated
min_days_since_publish1

工程质量

基础的工程与文档实践是否到位?

50中等 · 占总体的 20%

工程实践

24危急
评分方式
0/24CI 工作流
24/24存在测试
0/16Linter 配置
0/9.6Pre-commit 钩子
0/6.4.editorconfig
0/20OpenSSF Scorecard:CI-Tests — 0 out of 11 merged PRs checked by a CI test -- score normalized to 0
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config

文档

90优秀
评分方式
30/30README
25/25文档目录
15/15文档 / 主页站点 — https://docs.fest.build
10/10仓库描述
10/10主题标签 — 18 个主题标签
0/10Wiki
所用输入
topicsai, ai-agents, ai-tools, ai-workflow, ai-workspace, fest, festival-methodology, monorepo, navigation, claude-code, codex, git, opencode, cli, context-engineering, developer-tools, golang, project-management
has_wiki
homepagehttps://docs.fest.build
has_readme
has_docs_dir
has_description

安全

可见的安全与供应链实践是否稳固,且不存在未解决的高风险司法辖区暴露?

59中等 · 占总体的 16%

安全态势

49存在风险
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 0 out of 11 merged PRs checked by a CI test -- score normalized to 0
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
2.2/7.5Code-Review — Found 4/12 approved changesets -- score normalized to 3
2.5/2.5Contributors — project has 4 contributing companies or organizations
0/10Dangerous-Workflow — 无数据
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.2/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — 无数据
0/5Pinned-Dependencies — 无数据
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 — 无数据
0/7.5Token-Permissions — 无数据
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated13
scorecard_versionv5.5.0
checks_inconclusive5
scorecard_aggregate5
已排除计分(无数据或不适用):dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions。 其余权重已重新归一化。
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
0/25间接依赖不含已知公告 — 在此范围内,传递依赖集合无法与开发和测试依赖区分
0/40没有长期未处理的公告 — 没有公告带有发布日期
所用输入
sourceosv
advisories3
affected_packages3
assessed_packages106
unassessed_packages0
affected_by_severityunknown 3
direct_affected_packages0
已排除计分(无数据或不适用):间接依赖不含已知公告, 没有长期未处理的公告。 其余权重已重新归一化。 已将 106 个已解析依赖与 OSV 比对。 该仓库未发布任何索引可解析的软件包,因此改为评估仓库依赖图。该图将开发与测试版本固定同交付的依赖混在一起,因此仅对声明的运行时依赖计分;传递性发现仅作为背景信息列出,不计入评分。 未对可达性进行分析。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?这是一枚独立的实验性徽章——权重为 0.0,因此单独呈现,不影响总体健康评分。

60中等 · 占总体的 0%
评分方式
0/45代理指令 — 没有 CLAUDE.md / AGENTS.md / 编辑器规则
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 78 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.78
agent_instruction_files
agent_instruction_max_bytes
评分方式
18/18一条命令的引导启动 — justfile
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — Go(静态类型)
10/10可复现环境 — lockfile
0/10已体现的代理实践 — 最近 100 次提交中没有代理编写的提交
0/8自动化维护 — 未观察到自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — 无数据
所用输入
has_nix
has_tests
lockfilesgo.sum
has_dockerfile
typed_language
bootstrap_filesjustfile
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0
toolchain_manifestsgo.mod
dependency_bot_commit_share0
已排除计分(无数据或不适用):OpenSSF Scorecard:Pinned-Dependencies。 其余权重已重新归一化。
评分方式
45/45可类型检查的代码 — Go(静态类型)
55/55可控的文件大小 — 采样的 1,368 个源文件中有 1 个超过 60KB
所用输入
primary_languageGo
largest_source_bytes74,083
source_files_sampled1,368
oversized_source_files1

机器可读接口

40存在风险
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
0/20MCP 服务器
40/40可运行示例 — demos
所用输入
example_dirsdemos
has_mcp_signal
api_schema_files

关键数据

2GitHub 星标
2贡献者
1,960最近 12 个月提交数
0距最近推送天数
27发布版本数
1巴士系数(bus factor)
9开放议题
Go软件包生态系统数

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token

更多细节

OpenSSF Scorecard 5.0 / 10
5.0综合

来自开源项目 OpenSSF Scorecard 的独立、工具无关的安全评估。每项检查奖励的是安全实践本身,而非特定供应商的工具。Scorecard 无法判定的检查项标记为 不适用,并从安全评分中剔除(绝不按零分计)。Scorecard v5.5.0 · 2026-07-28 05:14 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
0CI-Tests0 out of 11 merged PRs checked by a CI test -- score normalized to 0
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
3Code-ReviewFound 4/12 approved changesets -- score normalized to 3
10Contributorsproject has 4 contributing companies or organizations
不适用Dangerous-Workflowno workflows found
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
9Licenselicense file detected
10Maintained30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
不适用Packagingpackaging workflow not detected
不适用Pinned-Dependenciesno dependencies found
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
不适用Token-PermissionsNo tokens found
7Vulnerabilities3 existing vulnerabilities detected
直接依赖 21
注册表软件包版本约束清单文件
Gogithub.com/Obedience-Corp/obey-sharedv0.4.5go.mod
Gogithub.com/alecthomas/chroma/v2v2.23.1go.mod
Gogithub.com/charmbracelet/bubblesv1.0.0go.mod
Gogithub.com/charmbracelet/bubbleteav1.3.10go.mod
Gogithub.com/charmbracelet/glamourv0.10.0go.mod
Gogithub.com/charmbracelet/huhv0.8.0go.mod
Gogithub.com/charmbracelet/lipglossv1.1.1-0.20250404203927-76690c660834go.mod
Gogithub.com/creack/ptyv1.1.24go.mod
Gogithub.com/google/uuidv1.6.0go.mod
Gogithub.com/ktr0731/go-fuzzyfinderv0.9.0go.mod
Gogithub.com/lancekrogers/guild-scaffoldv0.1.0go.mod
Gogithub.com/moby/patternmatcherv0.6.1go.mod
Gogithub.com/muesli/termenvv0.16.0go.mod
Gogithub.com/sahilm/fuzzyv0.1.1go.mod
Gogithub.com/spf13/cobrav1.10.2go.mod
Gogithub.com/spf13/pflagv1.0.10go.mod
Gogithub.com/stretchr/testifyv1.11.1go.mod
Gogithub.com/testcontainers/testcontainers-gov0.42.0go.mod
Gogolang.org/x/sysv0.47.0go.mod
Gogolang.org/x/termv0.45.0go.mod
Gogopkg.in/yaml.v3v3.0.1go.mod
全部依赖 106

来自 GitHub 依赖图的完整解析依赖集合:21 个直接依赖与 85 个间接(传递)软件包。仓库提交锁文件时,传递闭包才是完整的。

注册表软件包版本关系
Gogithub.com/alecthomas/chroma/v2v2.23.1直接
Gogithub.com/charmbracelet/bubblesv1.0.0直接
Gogithub.com/charmbracelet/bubbleteav1.3.10直接
Gogithub.com/charmbracelet/glamourv0.10.0直接
Gogithub.com/charmbracelet/huhv0.8.0直接
Gogithub.com/charmbracelet/lipglossv1.1.1-0.20250404203927-76690c660834直接
Gogithub.com/creack/ptyv1.1.24直接
Gogithub.com/google/uuidv1.6.0直接
Gogithub.com/ktr0731/go-fuzzyfinderv0.9.0直接
Gogithub.com/lancekrogers/guild-scaffoldv0.1.0直接
Gogithub.com/moby/patternmatcherv0.6.1直接
Gogithub.com/muesli/termenvv0.16.0直接
Gogithub.com/obedience-corp/obey-sharedv0.4.5直接
Gogithub.com/sahilm/fuzzyv0.1.1直接
Gogithub.com/spf13/cobrav1.10.2直接
Gogithub.com/spf13/pflagv1.0.10直接
Gogithub.com/stretchr/testifyv1.11.1直接
Gogithub.com/testcontainers/testcontainers-gov0.42.0直接
Gogolang.org/x/sysv0.47.0直接
Gogolang.org/x/termv0.45.0直接
Gogopkg.in/yaml.v3v3.0.1直接
Godario.cat/mergov1.0.2间接
Gogithub.com/atotto/clipboardv0.1.4间接
Gogithub.com/aymanbagabas/go-osc52/v2v2.0.1间接
Gogithub.com/aymerick/douceurv0.2.0间接
Gogithub.com/azure/go-ansitermv0.0.0-20250102033503-faa5f7b0171c间接
Gogithub.com/catppuccin/gov0.3.0间接
Gogithub.com/cenkalti/backoff/v4v4.3.0间接
Gogithub.com/cespare/xxhash/v2v2.3.0间接
Gogithub.com/charmbracelet/colorprofilev0.4.2间接
Gogithub.com/charmbracelet/x/ansiv0.11.6间接
Gogithub.com/charmbracelet/x/cellbufv0.0.15间接
Gogithub.com/charmbracelet/x/exp/slicev0.0.0-20260301212224-50d5c240f29a间接
Gogithub.com/charmbracelet/x/exp/stringsv0.1.0间接
Gogithub.com/charmbracelet/x/termv0.2.2间接
Gogithub.com/clipperhouse/displaywidthv0.11.0间接
Gogithub.com/clipperhouse/uax29/v2v2.7.0间接
Gogithub.com/containerd/errdefsv1.0.0间接
Gogithub.com/containerd/errdefs/pkgv0.3.0间接
Gogithub.com/containerd/logv0.1.0间接
Gogithub.com/containerd/platformsv0.2.1间接
Gogithub.com/cpuguy83/dockercfgv0.3.2间接
Gogithub.com/cpuguy83/go-md2man/v2v2.0.7间接
Gogithub.com/davecgh/go-spewv1.1.2-0.20180830191138-d8f796af33cc间接
Gogithub.com/distribution/referencev0.6.0间接
Gogithub.com/dlclark/regexp2v1.11.5间接
Gogithub.com/docker/go-connectionsv0.6.0间接
Gogithub.com/docker/go-unitsv0.5.0间接
Gogithub.com/dustin/go-humanizev1.0.1间接
Gogithub.com/ebitengine/puregov0.10.0间接
Gogithub.com/erikgeiser/coninputv0.0.0-20211004153227-1c3628e74d0f间接
Gogithub.com/felixge/httpsnoopv1.0.4间接
Gogithub.com/gdamore/encodingv1.0.1间接
Gogithub.com/gdamore/tcell/v2v2.13.8间接
Gogithub.com/go-logr/logrv1.4.3间接
Gogithub.com/go-logr/stdrv1.2.2间接
Gogithub.com/go-ole/go-olev1.2.6间接
Gogithub.com/gorilla/cssv1.0.1间接
Gogithub.com/inconshreveable/mousetrapv1.1.0间接
Gogithub.com/klauspost/compressv1.18.5间接
Gogithub.com/ktr0731/go-ansisgrv0.1.0间接
Gogithub.com/lucasb-eyer/go-colorfulv1.3.0间接
Gogithub.com/lufia/plan9statsv0.0.0-20211012122336-39d0f177ccd0间接
Gogithub.com/magiconair/propertiesv1.8.10间接
Gogithub.com/mattn/go-isattyv0.0.20间接
Gogithub.com/mattn/go-localereaderv0.0.1间接
Gogithub.com/mattn/go-runewidthv0.0.20间接
Gogithub.com/microcosm-cc/bluemondayv1.0.27间接
Gogithub.com/microsoft/go-winiov0.6.2间接
Gogithub.com/mitchellh/hashstructure/v2v2.0.2间接
Gogithub.com/moby/docker-image-specv1.3.1间接
Gogithub.com/moby/go-archivev0.2.0间接
Gogithub.com/moby/moby/apiv1.54.1间接
Gogithub.com/moby/moby/clientv0.4.0间接
Gogithub.com/moby/sys/sequentialv0.6.0间接
Gogithub.com/moby/sys/userv0.4.0间接
Gogithub.com/moby/sys/usernsv0.1.0间接
Gogithub.com/moby/termv0.5.2间接
Gogithub.com/muesli/ansiv0.0.0-20230316100256-276c6243b2f6间接
Gogithub.com/muesli/cancelreaderv0.2.2间接
Gogithub.com/muesli/reflowv0.3.0间接
Gogithub.com/nsf/termbox-gov1.1.1间接
Gogithub.com/opencontainers/go-digestv1.0.0间接
Gogithub.com/opencontainers/image-specv1.1.1间接
Gogithub.com/pkg/errorsv0.9.1间接
Gogithub.com/pmezard/go-difflibv1.0.1-0.20181226105442-5d4384ee4fb2间接
Gogithub.com/power-devops/perfstatv0.0.0-20240221224432-82ca36839d55间接
Gogithub.com/rivo/unisegv0.4.7间接
Gogithub.com/russross/blackfriday/v2v2.1.0间接
Gogithub.com/shirou/gopsutil/v4v4.26.3间接
Gogithub.com/sirupsen/logrusv1.9.4间接
Gogithub.com/tklauser/go-sysconfv0.3.16间接
Gogithub.com/tklauser/numcpusv0.11.0间接
Gogithub.com/xo/terminfov0.0.0-20220910002029-abceb7e1c41e间接
Gogithub.com/yuin/goldmarkv1.7.16间接
Gogithub.com/yuin/goldmark-emojiv1.0.6间接
Gogithub.com/yusufpapurcu/wmiv1.2.4间接
Gogo.opentelemetry.io/auto/sdkv1.2.1间接
Gogo.opentelemetry.io/contrib/instrumentation/net/http/otelhttpv0.60.0间接
Gogo.opentelemetry.io/otelv1.42.0间接
Gogo.opentelemetry.io/otel/metricv1.42.0间接
Gogo.opentelemetry.io/otel/tracev1.42.0间接
Gogo.yaml.in/yaml/v3v3.0.4间接
Gogolang.org/x/cryptov0.54.0间接
Gogolang.org/x/netv0.56.0间接
Gogolang.org/x/textv0.40.0间接
依赖安全公告 3

该仓库未发布可被索引解析的包,因此评估的是其自身的依赖图——共 106 个包,其中也包含从不交付的开发与测试版本固定:3 个存在已知公告,0 个为直接依赖。

软件包版本关系严重程度公告数修复版本
github.com/klauspost/compressv1.18.5间接未知11.18.7
github.com/yuin/goldmarkv1.7.16间接未知11.7.17
golang.org/x/cryptov0.54.0间接未知1

公告表示依赖图中记录的版本落入某条公告的受影响范围。可达性未经分析,且依赖图包含开发与测试的版本固定——某项发现可能只涉及工具链而非交付的软件。

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [
        "ai",
        "ai-agents",
        "ai-tools",
        "ai-workflow",
        "ai-workspace",
        "fest",
        "festival-methodology",
        "monorepo",
        "navigation",
        "claude-code",
        "codex",
        "git",
        "opencode",
        "cli",
        "context-engineering",
        "developer-tools",
        "golang",
        "project-management"
      ],
      "is_fork": false,
      "size_kb": 15854,
      "has_wiki": false,
      "homepage": "https://docs.fest.build",
      "languages": {
        "Go": 8293934,
        "Just": 31164,
        "Go Template": 87595
      },
      "pushed_at": "2026-07-28T03:31:00Z",
      "created_at": "2026-01-16T02:18:22Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-28T03:31:18Z",
      "description": "Workspace and context manager for domain specific AI automation and large scale AI workflows",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": "NOASSERTION",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": "https://obediencecorp.com/",
      "name": "Obedience Corp",
      "type": "Organization",
      "login": "Obedience-Corp",
      "company": null,
      "location": "United States of America",
      "followers": 6,
      "avatar_url": "https://avatars.githubusercontent.com/u/244234019?v=4",
      "created_at": "2025-11-15T19:57:24Z",
      "is_verified": null,
      "public_repos": 11,
      "account_age_days": 254
    },
    "license": {
      "state": "custom",
      "spdx_id": null,
      "raw_spdx": "NOASSERTION",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.3.1",
          "kind": "patch",
          "published_at": "2026-07-26T09:36:28Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-07-20T03:50:33Z"
        },
        {
          "tag": "v0.3.0-rc.3",
          "kind": "prerelease",
          "published_at": "2026-07-19T09:36:12Z"
        },
        {
          "tag": "v0.1.0-dev.1",
          "kind": "prerelease",
          "published_at": "2026-07-18T22:07:46Z"
        },
        {
          "tag": "v0.3.0-rc.2",
          "kind": "prerelease",
          "published_at": "2026-07-12T23:02:34Z"
        },
        {
          "tag": "v0.2.17",
          "kind": "patch",
          "published_at": "2026-07-02T22:49:16Z"
        },
        {
          "tag": "v0.2.16",
          "kind": "patch",
          "published_at": "2026-07-01T23:05:35Z"
        },
        {
          "tag": "v0.2.15",
          "kind": "patch",
          "published_at": "2026-07-01T19:48:17Z"
        },
        {
          "tag": "v0.2.14",
          "kind": "patch",
          "published_at": "2026-06-30T19:09:20Z"
        },
        {
          "tag": "v0.2.13",
          "kind": "patch",
          "published_at": "2026-06-30T10:17:00Z"
        },
        {
          "tag": "v0.2.12",
          "kind": "patch",
          "published_at": "2026-06-25T21:41:30Z"
        },
        {
          "tag": "v0.2.11",
          "kind": "patch",
          "published_at": "2026-06-22T23:33:12Z"
        },
        {
          "tag": "v0.2.10",
          "kind": "patch",
          "published_at": "2026-06-17T03:48:31Z"
        },
        {
          "tag": "v0.3.0-rc.1",
          "kind": "prerelease",
          "published_at": "2026-06-16T02:51:33Z"
        },
        {
          "tag": "v0.2.9",
          "kind": "patch",
          "published_at": "2026-06-15T23:07:37Z"
        },
        {
          "tag": "v0.2.8",
          "kind": "patch",
          "published_at": "2026-06-02T02:18:40Z"
        },
        {
          "tag": "v0.2.7",
          "kind": "patch",
          "published_at": "2026-05-29T16:40:34Z"
        },
        {
          "tag": "v0.2.6",
          "kind": "patch",
          "published_at": "2026-05-19T11:01:34Z"
        },
        {
          "tag": "v0.2.5",
          "kind": "patch",
          "published_at": "2026-05-01T03:55:29Z"
        },
        {
          "tag": "v0.2.4",
          "kind": "patch",
          "published_at": "2026-04-19T20:29:06Z"
        },
        {
          "tag": "v0.2.3",
          "kind": "patch",
          "published_at": "2026-04-19T20:26:50Z"
        },
        {
          "tag": "v0.2.2",
          "kind": "patch",
          "published_at": "2026-04-01T05:29:47Z"
        },
        {
          "tag": "v0.2.1",
          "kind": "patch",
          "published_at": "2026-03-31T22:26:37Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-03-25T06:23:51Z"
        },
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2026-03-11T09:48:43Z"
        },
        {
          "tag": "v0.1.1-rc.1",
          "kind": "prerelease",
          "published_at": "2026-03-11T09:30:57Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-03-10T19:58:33Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "43e1d4772a530536d5bed1b0d95226dda48d8eae",
          "body": "…es #512, #513) (#514)\n\nFixes #512 and #513. Both are test-infrastructure faults that made `just\ngate` and the integration suite unreliable signals, found while gating\nCA0004 phase 001.\n\nTest-only changes; no production code is touched.\n\n## #512 — lock tests measured the scheduler, not the lock\n\n`ju\n[…]\nlint issues in each, both\nunit suites.\n- `internal/fsutil` at `-count=60 -cpu=1,2` under twelve competing CPU\nhogs: clean.\n- Integration spot-check green; the harness change is inert on a healthy\nrun.",
          "is_bot": false,
          "headline": "test: make lock tests load-tolerant and container faults legible (fix…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-28T03:30:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2084117ff8b79abe9bddbe19e2ed155d6bdaaf5d",
          "body": "…ath signal, multi-member infra)\n\nSignal cancel-while-waiting from inside the contended wait loop via a\ntest-only hook so the test cannot collapse into the already-canceled path.\n\nArm run-level infrastructure death only after two distinct pool members\ndouble-fail Reset (one when pool size is 1), so a single wedged container\nfails locally without skipping healthy siblings under Docker headroom\ncascades still trip the run-level banner quickly.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] test: close remaining #514 residuals (wait-p…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-28T02:07:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1373920d28b3d3325c15728f86abbb4b9e128d8d",
          "body": "…r #514",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] test: polish lock/integration review nits fo…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-27T23:56:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1fef30105f9a7f0724cb430eaafec5e4dba62548",
          "body": "…ainer faults legible",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] test: make lock tests load-tolerant and cont…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-27T20:23:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "241aeb3556e2ef6cc06d100eeac74b9592404e4b",
          "body": "> **Independent of the MN0001 PR chain** (#504–#509). Based directly on\n`main`, small, and mergeable on its own. Worth taking first: it affects\nevery remote command today.\n\nA failed remote hop prints **nothing**. Not a vague message, nothing:\nexit 127 or 255 with empty stdout and empty stderr.\n\n```\n\n[…]\nites cannot. Every test in the repo passed with these messages being\ndiscarded, because no test asserted that a human ever sees them. It\nsurfaced the moment a real hop failed on a real second machine.",
          "is_bot": false,
          "headline": "fix(cli): stop discarding remote error messages (#510)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-27T01:18:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "794c3b909959b1bdd08d79b5465ad0e467eea853",
          "body": "… function\n\nReview: the comment said type assertion while the code used errors.As plus a\npointer-identity check, so a future reader would trust the comment over the\ncode. It is now the assertion the comment describes, which is equivalent and\nsays what it means.\n\nsilentExit also lived only in the test that exercised it, with a note to keep\nthe two identical by hand. It is production code now, so the test cannot pass\nwhile main does something else.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] refactor(cli): make the silent-exit rule one…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-27T00:32:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "187c7d0ed66dde1226a74a321c7d4a1d9a3c65fa",
          "body": "A failed remote hop printed nothing. Not a vague message, nothing: exit 127 or\n255 with empty stdout and empty stderr.\n\nmain() propagates a child process's exit code without printing, which is right\nfor camp sync, doctor, clone, and run, all of which return a CommandError\ndirectly and have already s\n[…]\nve fleet gate, which exists precisely to catch what unit\nsuites cannot: every test passed with the messages being discarded, because no\ntest asserted that a human sees them.\n\nGate green at 3740 tests.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(cli): stop discarding remote error messages",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-26T12:14:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "614dde1aa205661f2b19da5bc114d3aedbd09454",
          "body": null,
          "is_bot": false,
          "headline": "Update README.md",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-26T09:50:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "191c7560fd5d28306f45f92d7add700c9b8fe815",
          "body": "Reported by Fable.\n\n## The bug\n\nA link attaches an **active** workitem to a working location — almost\nalways a worktree, which is temporary by construction. `camp workitem\npromote --target completed|archived|someday` ends that, but promote left\nthe links in place and nothing downstream handled the r\n[…]\n` (incl. a `dungeonesque`\nfalse-positive guard)\n\n`just gate-fast`: 3761/3761 passed, 0 lint issues, both ratchets clean.\n\nIndependent of #502 (stale rows blocking link *writes*); no overlapping\nfiles.",
          "is_bot": false,
          "headline": "fix(workitem): promote to dungeon releases the workitem's links (#503)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-26T09:17:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d856fb0ccb16504c79babc671964e506d7e2d501",
          "body": "…too, and keep festival targets at error\n\nReview found the lifecycle rule was applied to only one of the two\npromote paths that shelve their source.\n\ndoDocPromote ends in appendShelve, which runs MoveToDungeon(..., 'completed')\nunless --keep. So promoting to a doc shelved the workitem and left its\nl\n[…]\nkeep pointing at it.\n\nAdds the end-to-end promote coverage the review asked for: dungeon\ntarget releases and reports, doc target releases, --keep does not. The\ndoc case fails against the pre-fix code.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(workitem): release links on doc promote …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-26T09:11:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a621788edf081a28fe0827608904eb33d4d79bb5",
          "body": "…he workitem's links\n\nA link attaches an active workitem to a working location -- almost always\na worktree, which is temporary by construction. Promoting a workitem to\ncompleted/archived/someday ends that, but promote left the links in\nplace, and nothing downstream handled the result.\n\nwkitem.Discov\n[…]\n layout still use the visible one) so the finding\nnames where the workitem went and why the link is going, instead of\nclaiming it is 'not present on disk'. The action is unchanged.\n\nReported by Fable.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(workitem): promote to dungeon releases t…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-26T09:11:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fd0c267b65fe12eafb00fba3b8a98bbd7a1d4c78",
          "body": "…e registry (#502)\n\n## The bug\n\nOne stale row in `.campaign/workitems/links.yaml` breaks every\nsubsequent link write in the campaign.\n\nBoth writers add the new link and then validate the **whole registry**,\nfailing on `errs[0]`:\n\n- `internal/commands/workitem/link.go` (`camp workitem link`)\n- `inter\n[…]\nDoesNotDeleteMachineLocalWorktreeLink`,\n`TestDoctorFix_StillRemovesAuthoritativelyDeadScope`,\n`TestStaleLinks_*`.\n\n`just gate-fast`: 111 packages, 3774/3774 passed, 0 lint issues, both\nratchets clean.",
          "is_bot": false,
          "headline": "fix(workitem): validate link writes against the new row, not the whol…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-26T09:10:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bb41988bfd6c9c3314e7709658a3ab6c4b56eb64",
          "body": "…al, and state the undo's real scope\n\nBoth review notes on the write-guard fix, neither cosmetic.\n\nThe undo was wrong about what it does. The prune and the caller's own\nwrite land in one save, so 'git checkout -- links.yaml' also discards\nthe link just created. A user running it to restore a pruned \n[…]\ng caller or for doctor. Every call site passes\ncmd.ErrOrStderr() today, so nothing changes in practice; the guard is\nthere so a future one cannot reintroduce silent data loss by leaving a\nfield unset.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(workitem): make prune reporting structur…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-26T09:05:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1900916ead3b2e43f73f66ab1ae2630a4668aa12",
          "body": "…s, protect machine-local ones\n\nFollow-up to the ValidateOne fix: writes no longer refuse on inherited\nrot, so camp should clear the rot it can prove rather than leave dead\nrows for the user to sweep.\n\nThe discriminator is whether a missing target means gone or only not\nhere. links.yaml is tracked, \n[…]\n relaxed for machine-local scopes;\n    escaping the campaign root still is not.\n\nVerified against a faithful mirror of a real 7-rot-row campaign: the\nlink succeeds, nothing is pruned, no notice fires.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(workitem): auto-clean provably dead link…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-26T07:31:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0b54f2af720b84f12fd4422033a8bdd557d05d80",
          "body": "…the new row, not the whole registry\n\nA stale row in links.yaml made every subsequent link write fail\ncampaign-wide. Both writers added the new link and then validated the\nentire registry, rejecting on errs[0] -- so one deleted worktree or\nrenamed workitem failed 'camp workitem link' and 'camp proje\n[…]\nt\ncamp workitem doctor --fix. It stays stat-level per the notice package\ncontract: one registry read plus one stat per row. Broken workitem_id\nreferences need a tree scan, so they stay doctor's alone.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(workitem): validate link writes against …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-26T06:45:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bf705da9327273c700502bdca92285c4c08c7170",
          "body": "## Summary\n\n- route Colima-backed integration runs through a suite-owned SSH\nUnix-socket tunnel\n- disable SSH ControlMaster reuse so Docker exec traffic cannot kill\nColima's lifecycle transport\n- raise the tunnel child's descriptor limit while preserving the parent\nprocess limit\n- health-check the p\n[…]\ne tests passed\n- verified `docker info` through Colima's global socket during and after\nthe full integration run\n- verified the suite-owned SSH process and temporary socket were removed\nafter teardown",
          "is_bot": false,
          "headline": "test(integration): isolate Colima Docker transport (#501)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-25T22:06:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ac7928345a20ae6692aa2233cae2b56a040f125f",
          "body": "…nsport",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] test(integration): isolate Colima Docker tra…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-25T22:00:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "716ffc2ebfd2f02b8d039c1eead2d7f23ae66240",
          "body": "## Summary\n\n- align the fresh-sweep integration fixture with Fest's real\npost-completion workflow state\n- reuse the shared `stampCompletedRun` helper so fresh and direct sweep\ntests exercise the same contract\n\n## Root cause\n\nThe latest-run eligibility fix correctly requires a completed run in\n`workf\n[…]\nests passed\n- a subsequent full integration rerun was blocked before test execution\nwhen the Colima host socket became unavailable; the exact affected\nintegration group had already passed in isolation",
          "is_bot": false,
          "headline": "test(fresh): align sweep fixtures with completed runs (#500)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-25T21:12:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7509840b85a0b16f6c382a40d8346b98b0ee7d65",
          "body": null,
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] test(fresh): use completed-run sweep fixture",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-25T21:05:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "46eb6e8bfa77120186185b382aa7a8041165e930",
          "body": "… never fired) (#499)\n\n## Summary\n\nFixes a correctness bug in the tier-1 workitem sweep (shipped in\n#493/#494): as\nmerged, `camp workitem sweep` never fires on a genuinely completed\nworkitem. This\nwas found by spike B of the WF0001 verification-spikes sequence\n\n(`003_FESTIVAL_RAIL/01_verification_sp\n[…]\nd`\nfield is\nrenamed to `run_id` (the feature is fresh and the value is the\ncompleted, not\n  active, run); called out here as a deliberate contract correction.\n\nNot merged by an agent; left for review.",
          "is_bot": false,
          "headline": "fix(sweep): key tier-1 eligibility on the latest completed run (sweep…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-25T17:07:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e8ef64e23d209d102f02a85351f8412724b594e9",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into fix/sweep-latest-run-eligibility",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-25T17:02:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6990a7357e159ba1f22bd46302b69d128cf20468",
          "body": "…surface latest_run_status in TUI\n\nReview follow-ups on #499.\n\nlatestRunID had no multi-entry coverage: the only test through that path\ncarries a single completed run, leaving newest-by-ended_at, tie-break,\nempty run_id, and all-empty ended_at unexercised on the function that\ndecides which run the s\n[…]\nrPreview itself and\nfails without the fix.\n\ngather_plan's RunStatus switch was checked and needs no fallback: it\nreturns early when ActiveRunID is empty, so RunStatus is only read while\na run is live.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] test(workitem): cover latestRunID ordering; …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T21:53:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "67b820abde381d65ab4fe5a0676ccd7079134bb0",
          "body": "…S2) (#497)\n\n## Summary\n\nCompletes the tier-2 merged-branch backstop with the interactive prompt:\non a\nTTY, `camp fresh` now asks per surviving match whether to promote the\nworkitem to\ncompleted, and promotes on accept with `merged_branch` evidence. Final\nsequence\nof phase 002 of the `workitem-festi\n[…]\n   Skip all     Keep asking\n←/→ toggle • enter submit • y Skip all • n Keep asking\n```\n\n`just gate` green (0 lint issues, both ratchets; gate-fast 3751/3751).\n\nNot merged by an agent; left for review.",
          "is_bot": false,
          "headline": "feat(fresh): interactive tier-2 merged-branch prompt flow (WF0001 P2/…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T21:22:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1aad9188c2f064dadf4ea9e44543ba199448f587",
          "body": "…ket they report (#498)\n\n## Summary\n\n`TestMachineDiagnoseControlMasterLifecycle` has been failing since #492.\nIt is not a flaky test: #492 added a per-machine camp version probe to\n`camp machine diagnose`, and that probe hops with `ControlMaster=auto`.\nAgainst a **stale** ControlPath, OpenSSH unlink\n[…]\n master behind for a subsequent hop.\nThat is the intended cost: a surface that reports socket state must not\nmutate it. Operators who want a warm master get one from `camp switch`,\nwhich is unchanged.",
          "is_bot": false,
          "headline": "fix(machine): stop diagnose probes from healing the ControlMaster soc…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T20:58:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dcf3b2669d355a1d56859866ca3f2db7bc0c8fda",
          "body": "…/S1) (#496)\n\n## Summary\n\nAdds the tier-2 merged-branch backstop mapping and open-work guard,\nwired into\n`camp fresh` in report mode. When fresh prunes a merged branch, it maps\nthat\nbranch back to a still-active workitem and (in `report` mode) prints the\nexact\n`camp workitem promote` command, infere\n[…]\n workitem promote\ndesign-myfeature --target completed` and the workitem is not moved.\n`just lint`\nclean (0 issues, both ratchets); `just test unit` 3702/3702.\n\nNot merged by an agent; left for review.",
          "is_bot": false,
          "headline": "feat(fresh): tier-2 merged-branch backstop mapping + guard (WF0001 P2…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T20:12:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8c72f70fa4c3367c06c99dbe384be65afb23b931",
          "body": "…1/S3) (#495)\n\n## Summary\n\nWires the tier-1 workitem sweep into `camp fresh` behind a\n`completed_runs`\nsetting and adds a read-only \"N workitems have completed runs\" banner to\n`camp wi`. Third and final sequence of phase 001 of the\n`workitem-festival-lifecycle` festival (WF0001), spec `WI-75d77f` do\n[…]\n). The\nonly failure is the pre-existing\n`TestMachineDiagnoseControlMasterLifecycle`\n(SSH ControlMaster, machine-diagnose subsystem; untouched by this\nbranch).\n\nNot merged by an agent; left for review.",
          "is_bot": false,
          "headline": "feat(fresh,wi): tier-1 sweep in camp fresh + camp wi banner (WF0001 P…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T20:11:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e37530f248a2183e93b746fd11555d5f71d756e1",
          "body": "…mpleted run, not a set active_run_id\n\nRoot cause: fest clears active_run_id from .workflow/workflow.yaml the instant a\nrun completes (fest localstore store.go:321-323), and camp's LoadLocalRunFS only\nreads the run referenced by active_run_id (localrun.go:105 gate). So a genuinely\ncompleted standalo\n[…]\nto completion and asserts camp workitem sweep\n  actually promotes the item (acceptance bar)\n\nImplements the finding in 003_FESTIVAL_RAIL/01_verification_spikes/results/spike-b-localrun-eligibility.md.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(sweep): key eligibility on the latest co…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T20:09:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4f0a6de127eea838a8ac9e5c334788701529a087",
          "body": "…romotes; thread resolved cfg\n\nReview #497:\n- BLOCKING: a dry-run with default prompt on a TTY could reach PromoteMergedWorkitem and mutate (deletedNames includes StatusWouldDelete). resolveBackstopMode downgrades a dry-run to report-only (mirrors the tier-1 sweep), so the prompt/promote path is unr\n[…]\nwd; handleMergedBackstop loads cfg once via LoadCampaignConfig(root) and threads it through MapMergedBranchesToWorkitems and the promote path, so a non-root cwd with a threaded campRoot cannot diverge",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(fresh): dry-run backstop never prompts/p…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T19:53:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0f3dc50b0aebf1dd8ae491bfa80511ff33eccf89",
          "body": "…prompt-flow",
          "is_bot": false,
          "headline": "Merge branch 'fest/wf0001-p2s1-branch-mapping' into fest/wf0001-p2s2-…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T19:13:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9125fb48689e58df678c51d3ffb224bbc3cc6623",
          "body": "…s1-branch-mapping",
          "is_bot": false,
          "headline": "Merge branch 'fest/wf0001-p1s3-fresh-integration' into fest/wf0001-p2…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T19:13:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bff55aab4f08c495d27ac94bf7d63b45304226d9",
          "body": "…h-integration",
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'origin/main' into fest/wf0001-p1s3-fres…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T19:13:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f187ea62a526519c743747e859300ca1b39dbae9",
          "body": "…h prompt flow\n\n- Flip merged_workitems default from off to the spec value prompt\n- Add EvidenceMergedBranch constant; export PromoteMergedWorkitem (reuses sweepOne to move a workitem to completed with a given evidence)\n- handleMergedBackstop prompts on a TTY (mode prompt) via two huh.NewConfirm ste\n[…]\nve flow pty-verified (render + promote-on-accept + skip-all); source dir gone after accept\n\nCompletes phase 002 tier-2. Stacks on the branch-mapping sequence (updated with the #495/#496 review fixes).",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] feat(fresh): interactive tier-2 merged-branc…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T18:54:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "42f90e67da60d6530803bd38398ce593432025dd",
          "body": "…ing the socket they report\n\ncamp machine diagnose gained a per-machine camp version probe, which hops\nwith ControlMaster=auto. Against a stale ControlPath, OpenSSH unlinks the\nsocket and opens a fresh master, so diagnose healed the exact stale state\nit was reporting: 'diagnose self' read stale, the\n[…]\nced a stale socket while the screen\nkept showing stale. switch/ResolveRoot keep ControlMaster=auto, preserving\nthe one-auth resolve-plus-hop property.\n\nFixes TestMachineDiagnoseControlMasterLifecycle.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(machine): stop diagnose probes from heal…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T18:41:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "89f4bf84409df44c8f0349968e8862bec9b90d2f",
          "body": "…parison + ctx + beforeSHA log\n\nReview #496:\n- BLOCKING: HasOpenWork now compares project/repo links against the just-pruned project's campaign-relative path (not the matched worktree scope path), so a workitem with both a project link and its own just-merged worktree link no longer reads as perpetu\n[…]\ntead of context.Background()\n- beforeSHA rev-parse error/empty is logged (dim, best-effort) instead of silently ignored; commit-tag scan is skipped for that project, worktree-link matching still works",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(fresh): open-work guard project-path com…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T18:38:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e82b61529b7f0595ae900fb9d7e4bd265f4a72fe",
          "body": "…1 P1/S2) (#494)\n\n## Summary\n\nAdds `camp workitem sweep`, the tier-1 mutation path of evidence-driven\ncompletion: it promotes every workitem whose active workflow run has\ncompleted\nto that item's local `dungeon/completed`. Second sequence of the\n`workitem-festival-lifecycle` festival (WF0001), spec \n[…]\n as\nfailed, self-healing since the item is now in the dungeon and excluded\nfrom\nre-sweep). Same non-atomicity promote has; documented in the sequence\nreview.\n- Not merged by an agent; left for review.",
          "is_bot": false,
          "headline": "feat(workitem): camp workitem sweep verb for tier-1 completion (WF000…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T18:34:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b3629bba5a61702fa47924aebe75db3f94320f82",
          "body": "… rule (WF0001 P1/S1) (#493)\n\n## Summary\n\nAdds the pure sweep-eligibility planner and the local-dungeon\ndestination\nresolver that the tier-1 evidence-driven completion feature is built on.\nThis is\nthe first sequence of the `workitem-festival-lifecycle` festival\n(WF0001), spec\nof record `WI-75d77f` d\n[…]\nse 1. This sequence\nverifies it now via `TestPlanSweep_MultiRunCaveat` rather than\ndeferring.\n  Written up in the sequence's `results/testing-and-verify.md`.\n- Not merged by an agent; left for review.",
          "is_bot": false,
          "headline": "feat(workitem): sweep eligibility planner + local-dungeon destination…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T18:34:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "faaeb01dcc0e149b284719da9c17e6ae7e6f5d97",
          "body": "…s1-branch-mapping",
          "is_bot": false,
          "headline": "Merge branch 'fest/wf0001-p1s3-fresh-integration' into fest/wf0001-p2…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T18:30:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "07ddb3bc16f84667e0f767adca5aa8c768a0843f",
          "body": "… mid-sweep context cancellation\n\nReview #495:\n- SweepBannerText(1) now reads '1 workitem has completed runs' (singular verb agreement); update the wording unit test and loosen the fresh report integration assertion\n- executeSweepCandidates returns ctx.Err() instead of a bare return, so a cancelled mid-sweep propagates through runWorkitemSweep and RunFreshSweep rather than reporting a clean success (regression from the #494 loop); add TestExecuteSweepCandidates_ContextCancelledPropagates",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(sweep): singular banner verb + propagate…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T18:30:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b1b2e1a7d243812c907b66f69ddd4772be7ac69b",
          "body": null,
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] style(fresh): drop emdash from backstop comment",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T12:52:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7aacb39bb9a1a8d245bf1b6e0deaa7dc6f6124f0",
          "body": "…tests + guard scope-path fix\n\n- Add ScopePath to MergedBackstopMatch so the open-work guard excludes the just-merged worktree itself (a worktree-linked match whose dir still exists was wrongly suppressed); HasOpenWork now uses the matched scope path\n- Add end-to-end integration tests (tests/integration/fresh_merged_backstop_test.go): worktree-link reported via camp fresh with the exact promote command and no move, off mode silent, no-match silent",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-FE-WF0001] test(fresh): backstop integration …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T12:46:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "12ae14a2c07d43c79fc8fe9e1b74e3ba70615e66",
          "body": "…backstop mapping, guard, and report wiring\n\n- Add MapMergedBranchesToWorkitems + MergedBackstopMatch in internal/commands/fresh/merged_backstop.go: maps a project's just-pruned branches to still-active workitems via worktree-scope links (branch name == worktree dir basename) and WI- commit tags on \n[…]\nd logic\n\nTier-2 of the WI-75d77f evidence-driven completion spec (doc 03). The interactive TTY prompt + merged_branch evidence promote land in the next stacked sequence. Stacks on phase 001 (PR #495).",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-FE-WF0001] feat(fresh): tier-2 merged-branch …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T12:36:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dfc56fedfa067b1b60569ee049555894c500b7e3",
          "body": "…m sweep in camp fresh + camp wi banner\n\n- Add completed_runs fresh setting (sweep|report|off, default sweep) with ResolveFreshCompletedRuns; campaign-root scoped like prune\n- Wire the sweep once per camp fresh invocation (single-project RunE and after the runFreshBatch loop), never inside executeFr\n[…]\nte-per-project-failure; unit tests for the resolver and banner; TUI verified in a pty\n\nTier-1 evidence-driven completion habitual trigger (WI-75d77f docs 03, 05). Stacks on the sweep command sequence.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-FE-WF0001] feat(fresh,wi): run tier-1 workite…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T12:11:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "56898a8f207332235617ef06d351ce54e77bdea3",
          "body": "…sweep verb for tier-1 completion promotion\n\n- Add camp workitem sweep: gathers workitems, plans via PlanSweep, promotes each eligible item to its local dungeon/completed through the existing MoveToDungeon path, with per-item error isolation (one failure never aborts the batch)\n- Add --dry-run (read\n[…]\nainerized integration scenarios plus host unit tests for the JSON envelope\n\nTier-1 mutation path from the WI-75d77f evidence-driven completion spec (docs 03, 05). Stacks on the sweep planner sequence.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-FE-WF0001] feat(workitem): add camp workitem …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T11:42:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4035125d2505f722e3c4e802435799eeea5e628b",
          "body": "…ity planner and local-dungeon destination rule\n\n- Add PlanSweep pure planner in internal/workitem (SweepCandidate, EvidenceWorkflowRunCompleted): filters gathered workitems to tier-1 auto-promotion candidates (completed active run, non-festival/intent type, non-dungeon path), zero I/O\n- Add resolve\n[…]\n a newly started active run\n\nFoundation for camp workitem sweep (sequence 02) and fresh integration (sequence 03): the tier-1 staleness fix from the WI-75d77f evidence-driven completion spec (doc 03).",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-FE-WF0001] feat(workitem): add sweep eligibil…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T11:07:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1d8397a6bba2aa4e035dc036af192578b1709682",
          "body": "…back (#492)\n\nFollow-up to #486 driven by the live operator gate on WI-56d496. Intent:\nremote-surfaces-v2-gate-feedback.\n\n## Changes\n\n1. **List TUI auto-loads remotes on open** when machines.yaml is\nnon-empty (async via tea.Cmd, fail-open; locals render immediately,\nremote rows append). `r` now hide\n[…]\nlocals immediately, auto-load fails open with `loaded remotes (1\nunreachable: deadbox)` status, `--remote` opens the TUI in a TTY, piped\n`--remote` still prints the MACHINE table.\n\nWorkitem: WI-56d496",
          "is_bot": false,
          "headline": "feat(list,switch,machine): remote surfaces v2 from operator gate feed…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T09:37:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9e37424b24f5f290a11d5b1d0fd96c81ec3eeb56",
          "body": "## Summary\n\n- add the explicit `CAMP_COMMIT_AMEND=1` contract for auto-write\ncommit-message hooks\n- send the amend signal from root, project, and worktree commit paths\n- document the hook environment and cover helper plus subprocess\npropagation\n\n## Why\n\nCommit-message writers cannot safely infer ame\n[…]\nommit` can generate a message for the complete\namended commit while ordinary auto-write behavior remains unchanged.\n\n## Validation\n\n- `just test unit` — 3,678/3,678 tests passed\n- `just lint` — passed",
          "is_bot": false,
          "headline": "feat(commit): signal amend mode to message writers (#490)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T09:37:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "42145d554859a3e578ed3c67b9302e8f549b0856",
          "body": "…nteractive wrapper (#491)\n\n## The bug\n\nThe interactive `camp` shell wrapper (installed via `camp shell-init\n<shell>`) wraps `camp` in a shell function so directory-changing\ncommands can `cd` the caller. Its workitem arm appended `--path-output\n<tmpfile>` to every `camp workitem ...` invocation on a\n[…]\nlint` stable + dev (0 issues each), unit tests dev (3725 passed)\nand stable (3680 passed).\n- No CLI help text changed, so no `just docs` regeneration was needed.\n\nNo pre-existing failures encountered.",
          "is_bot": false,
          "headline": "fix(shell): stop appending --path-output to workitem subcommands in i…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T09:36:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "aae497f6125b12d1f69b3eb15c8c14c281699a7e",
          "body": "…surfaces v2 from operator gate feedback\n\n- list TUI: remotes auto-load on open when machines are configured (async,\n  fail-open); r now hides or reloads\n- camp list --remote opens the same TUI in a TTY; pipes and --json keep the table\n- switch picker: remote load failures and unreachable machines p\n[…]\ncompletion cache\n- machine diagnose: probes remote camp version, warns on skew (old fleet\n  binaries produced misleading selector errors)\n- list TUI tests isolated from the runner's real machines.yaml",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-56d496] feat(list,switch,machine): remote …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T07:57:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dc255cc66d6926c27fa4e6c600d426d074b420fd",
          "body": "…workitem subcommands in interactive wrapper\n\nThe interactive camp shell wrapper (zsh/bash/fish) appended\n--path-output <tmpfile> to every 'camp workitem ...' invocation on a\nTTY unless --help/--json/--print was present. That append is only valid\nfor the bare interactive dashboard; workitem subcomma\n[…]\nutput too.\n\nApplied identically to all three shells and covered by extended\nwrapper-transparency tests asserting the subcommand guard precedes the\n--path-output interception in each generated wrapper.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(shell): stop appending --path-output to …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T07:53:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "18a7e853622fbc6d446259a8ec883c7788497ba1",
          "body": "…riters",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] feat(commit): signal amend mode to message w…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T07:44:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6877f682d927bdb2e861abaf9d40f593f6700521",
          "body": "## Summary\n- Document that shell-init defines `camp` as a shell function, so plain\n`which camp` prints the function body instead of a path.\n- Show the correct discovery commands: `whence -p` / `which -p` (zsh),\n`type -P` (bash), `type -a`, and `realpath`.\n- Fix the README troubleshooting tip that in\n[…]\nn\n- [ ] Read the new README and shell-integration sections for clarity\n- [ ] After `eval \"$(camp shell-init zsh)\"`, confirm `whence -p camp`\nreturns a binary path while `which camp` shows the function",
          "is_bot": false,
          "headline": "docs: explain how to find camp binary path after shell-init (#489)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T07:43:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "413eaf38f6b07dd7b24e55f1bdd2bc66213b840a",
          "body": "…aths after shell-init\n\nShell integration defines camp/fest as shell functions so navigation can\ncd. Plain `which` prints the function body; document whence -p / type -P\nand realpath instead.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] docs: explain how to find camp/fest binary p…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T07:42:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a99f5d6383248152af4a546176e0cd98900f13a",
          "body": "…geon (#488)\n\n## Summary\n\nQuest scaffolding never adopted camp's dungeon spelling layer, so it\nhardcoded\nthe visible `.campaign/quests/dungeon` path. Two bugs followed:\n\n1. Every quest command that runs `EnsureScaffold` (`create`, `use`,\n`list`, ...)\nrecreated a visible `.campaign/quests/dungeon/` e\n[…]\neon\nexists.\n- No auto-healing of a pre-existing both-spellings state (see the repro\nnote\nabove); the conflict is surfaced loudly and reconciled once by the user,\nsame\n  as every other dungeon in camp.",
          "is_bot": false,
          "headline": "fix(quest): adopt dungeon spelling layer, stop recreating visible dun…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T05:41:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "da766a208dae8f369fb34182beecb4770323f51d",
          "body": "…t + regression integration\n\nUnit: table-driven resolution precedence (only .dungeon, only visible dungeon,\nboth -> conflict, campaign-established spelling propagates, empty campaign +\ndungeon_hidden true/false), plus EnsureQuestDungeon never creating a visible\ndungeon beside a hidden one.\n\nIntegrat\n[…]\n visible dungeon and lists\nthe dungeoned quest; a quest pre-filed under .dungeon is visible again in\nlist --all; a legacy visible campaign keeps using the visible dungeon and never\ngrows a hidden one.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] test(quest): dungeon spelling precedence uni…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T05:13:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a8410581b7a8f22631e7e48684a89806d0f2e97e",
          "body": "…op recreating visible dungeon\n\nQuest scaffolding hardcoded .campaign/quests/dungeon, so every quest command\nthat ran EnsureScaffold (create, use, list, ...) recreated a visible dungeon\neven on a campaign migrated to the hidden .dungeon spelling, and quests already\nfiled under .dungeon were invisibl\n[…]\niles completed/archived quests into it.\n\nUpdates the scaffold init tests, which encoded the bug by expecting a visible\nquest dungeon while every other dungeon in the same hidden campaign was\n.dungeon.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(quest): adopt dungeon spelling layer, st…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T05:13:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eff6a0df93f7ba5ab3acd32cdb2a441fb04e3f42",
          "body": "Follow-up to #486 (merged while the lint fix was in flight).\n\n`just gate` failed on main-bound code with staticcheck QF1012\n(WriteString(fmt.Sprintf) -> fmt.Fprintf) in the switch picker preview\nhelpers, plus one minmax modernization. No behavior change; all 3650\ntests pass and `just gate` is green with this commit.\n\nWorkitem: WI-56d496",
          "is_bot": false,
          "headline": "fix(lint): staticcheck cleanups in switch_pick preview (#487)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T05:01:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "db89ad56f3f15a92e688f7ebe24c061b7bc7395c",
          "body": "## Summary\n\nAdds `camp workitem id [selector-or-path]`, a read-only command that\nprints a workitem's durable identifier. It is the identifier sibling of\nthe existing `camp workitem --print` (which prints a path): the bare id\ngoes to stdout so scripts and agents can capture it.\n\n## Output contract\n\n-\n[…]\nscripts/agents that call the binary\ndirectly or pass `--json` (which passes through cleanly), so it is left\nas-is; making the wrapper pass through recognized subcommands is a\nseparate, broader change.",
          "is_bot": false,
          "headline": "feat(workitem): add camp workitem id verb (#485)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T05:01:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "62310943fee682b153f309636dc1247fe2052f93",
          "body": "…tring(Sprintf) in switch_pick preview; minmax modernize",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-56d496] fix(lint): fmt.Fprintf over WriteS…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T04:54:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2e5126d3d9b417867ef07e4b02b254f2084d2eb1",
          "body": "…kitem id\n\nRegenerated via just docs after adding the workitem id subcommand.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] docs(cli-reference): regenerate for camp wor…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T04:54:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6d2fce56a29bc5afcf7bd20adf5e518aec7fda0c",
          "body": "Add a read-only camp workitem id subcommand that prints a workitem's\ndurable identifier. It is the id sibling of camp workitem --print\n(which prints a path): the bare id goes to stdout for shell scripting.\n\nResolution is a thin veneer over the resolver used by camp workitem\nresolve. With no argument\n[…]\ngument is\na clear stderr error with nonzero exit, never a hang or prompt.\n\nDynamic shell completion for the positional argument feeds durable ids\nfrom the same gather that serves camp workitem --json.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] feat(workitem): add camp workitem id verb",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T04:54:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b04b264cf2856e1084f97bb94bf3deb0c99f8bfa",
          "body": "… (#486)\n\n## Summary\n\nImplements design **WI-56d496** (remote list/switch discoverability) on\ntop of dual-auth #481.\n\nOperators can already **connect** (`csw machine:campaign`) but could not\n**see or pick** remotes from ordinary list/switch surfaces. This PR:\n\n1. **Switch picker (R3/R5)** — Opens im\n[…]\nop\n  ```\n\n## Design refs\n\n- Campaign design:\n`workflow/design/machine-remote-list-switch-surfaces/` (WI-56d496)\n- Fathom amendments: non-blocking picker open; TTY-gated table hint;\nasync list TUI load",
          "is_bot": false,
          "headline": "feat(list,switch): surface remote machines in picker and list browser…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T04:53:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8f6773e71f9fa393e06be04868475342ae297699",
          "body": "## What this adds\n\n`camp workitem rename <selector> <new-name>` renames a workitem's\ndirectory or\nfile basename while keeping its identity coherent. Only the path\nbasename\nchanges: the stable id, ref, title, workflow type, and lifecycle status\nare\nuntouched. Every path-derived reference is repaired \n[…]\n    | 2 +-\n workflow/design/{timeline => release-timeline}/.workitem | 0\n workflow/design/{timeline => release-timeline}/README.md | 0\n workflow/design/{timeline => release-timeline}/sub/x.md  | 0\n```",
          "is_bot": false,
          "headline": "feat(workitem): add camp workitem rename verb (#484)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T04:52:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8d0e22618760417c6a12b61f8db2e6118c93d330",
          "body": "## Summary\n\n`camp quest create` gains an optional workitem binding at creation time,\non both\nsurfaces:\n\n- **Non-interactive:** a new `--workitem <selector>` flag.\n- **Interactive TUI:** an optional final picker step where you\nfuzzy-search\n  workitems and bind one, or skip.\n\nA quest can now be create\n[…]\nate choice, not an oversight.\n- The picker filter uses subsequence fuzzy scoring per\nwhitespace-separated term\n(all terms must match). Deliberately simple and predictable; no ranking\nconfig\n  exposed.",
          "is_bot": false,
          "headline": "feat(quest): optional workitem binding in quest create (#483)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-24T04:52:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0ea70da5ae459b3238849203d67f58a6fa78ce61",
          "body": "…machines in picker and list browser\n\nImplement WI-56d496 remote discoverability: interactive switch picker loads\nlocal rows immediately and appends remotes via fuzzyfinder hot reload; list TUI\ntoggles remotes with r (async tea.Cmd); table path emits a TTY-gated machines\nhint; shell list arms hop on ssh-hop: path-output markers. Hop contract and\nBatchMode dual-auth paths are unchanged.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-56d496] feat(list,switch): surface remote …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-23T23:39:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f8818a5a8364d4ec12a6004b9d31bdb6b4ced111",
          "body": "…item rename",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] docs(cli): regenerate CLI reference for work…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-23T23:07:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cb3811bb40bd39208652d5616065a95453ff0d30",
          "body": "…ce repair\n\nAdd camp workitem rename <selector> <new-name>, which changes a\nworkitem's directory or file basename while keeping identity coherent.\nThe move reuses the same primitives promote uses (statusmove for the\nphysical move, mdlinks for markdown link rewriting) and repairs every\npath-derived r\n[…]\n old path key. Festivals and intents are rejected because their\nidentity is owned by other tooling. File workitems preserve their\nextension. stable_id, title, type, and lifecycle status are unchanged.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] feat(workitem): add rename verb with referen…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-23T23:06:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "445671e442ab3342fc31a73145dd4ac2a6aafd93",
          "body": "Use a plain hyphen rather than an emdash in the picker none/skip row so the\nuser-facing label stays free of emdashes.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] style(quest): hyphen in picker skip label",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-23T23:04:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9e5336f0db21eb4172b03c44bced2caedb3160fc",
          "body": "…create workitem binding\n\nContainer-based tests covering the binding flow end to end: bind by slug and\nby path, fail-fast on a bad selector (no orphan quest created), and the\nbinding landing in the same create commit with no dirty quest file left\nbehind.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] test(quest): integration coverage for quest …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-23T23:02:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e64e06e3983140b5256783f1552058e2cb592651",
          "body": "… to quest create\n\nBind a workitem to a new quest via --workitem <selector>, resolved through\nthe same selector family the workitem commands use (ref, stable id, key,\npath, directory slug, festival id). The selector is resolved up-front so a\nbad selector fails before any quest is written, leaving no\n[…]\n camp quest link),\nso camp quest show and camp quest links render it with no changes. The link\nlands in the same create commit. The interactive picker is offered only when\n--workitem was not supplied.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] feat(quest): add --workitem flag and binding…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-23T23:02:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eb24018f1f61d0dce94eb8de05b2baba88dd9eb2",
          "body": "…r in quest create TUI\n\nAdd an optional final step to the interactive quest-create flow that lets\nthe user fuzzy-search discovered workitems (by name, ref, or festival id)\nand bind one, or skip with a single Enter on the none row or Esc. The step\nonly appears when candidate workitems exist, so campa\n[…]\nr flow, and the fast path stays a single Enter to skip.\n\nThe picker reuses the nav/fuzzy scorer and house TUI styles; candidates are\ninjected by the command layer so the model stays pure and testable.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] feat(quest): optional workitem binding picke…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-23T23:02:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "79be4b9a192f564ed06e05ef12c6ca59622c947e",
          "body": "## Summary\n\n- align machine-discovery integration expectations with the intentional\n`ssh-agent` default while retaining explicit `tailscale-ssh` coverage\n- preserve the exact worktree `camp fresh` detaches while reclaiming the\ndefault branch\n- continue pruning unrelated merged detached worktrees\n\n##\n[…]\nssion cases\npass\n- `just gate-fast` passes, including stable/dev builds, vet, lint, and\n3,669 unit tests\n- full container integration suite passes: 537/537 tests in 449.86s\n- `git diff --check` passes",
          "is_bot": false,
          "headline": "fix: restore Camp integration suite consistency (#482)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-23T22:12:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e204d9f62306fb93784ac15ef03e7d0a1aebb874",
          "body": "…e preservation\n\nAddress PR #482 review. The reclaim path detaches the former default-branch\nworktree at merged history, so the same run's prune pass would delete it unless\nfresh preserves that path (PreserveDetachedWorktrees). Nothing asserted that:\nTestFresh_ReclaimsDefaultBranchFromOtherWorktree \n[…]\nble).\nVerified to fail without the fresh.go preserve wiring and pass with it.\n\nRewrite the misleading --no-prune comment on the existing reclaim test, which\ndocumented the old delete-after-detach bug.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] test(fresh): lock reclaim-then-prune worktre…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-23T22:09:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9d61b1bc4874a89a592c56e6111e7595759c57b9",
          "body": null,
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix: restore integration suite consistency",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-23T17:57:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4cfed5c90c2e6d9375961303bfd9fe869dfa3375",
          "body": "## Summary\n\nShips the locked dual-auth connectivity contract for `camp machine`\n(design WI-ca06e1 / D1–D7) so OpenSSH and Tailscale SSH are first-class\nbefore the next release.\n\n- **Discover defaults to OpenSSH** (`ssh-agent`); Tailscale SSH is\nopt-in via `--auth tailscale-ssh` or TUI cycle\n- **Hono\n[…]\neck-mode / permission-denied messages (unit fixtures)\n- [ ] Manual: existing machines.yaml entries unchanged; no BatchMode=no\nregression\n\nDesign: `workflow/design/camp-machine-tailscale-connectivity/`",
          "is_bot": false,
          "headline": "feat(machine): dual-auth discover defaults and hop error classes (#481)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T23:23:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1b627d54781a1e9374e60e17c8fdb4feeee15690",
          "body": "…e fleet TUI, not CLI\n\nSeed machines off-screen so the recording is the two-pane camp machine TUI:\nselect machine, help, edit auth (OpenSSH/Tailscale SSH), tailnet scan.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-ca06e1] docs(demos): machine-tui.gif is th…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T22:45:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d8d70ac6e6aa7914db0c33f75c85c65a6a568aa",
          "body": "…uality (compact, no dither)\n\nRe-record at 1000x640 with truecolor, avoid password-auth / DNS-fail ending,\nand palette-encode without bayer dither so text is not corrupted.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-ca06e1] docs(demos): fix machine TUI GIF q…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T06:47:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8003f7220e8bc1b0aadb554c376b5fcc1de5683a",
          "body": "…onflict with main\n\nKeep both machine dual-auth and worktree-list demo rows after merging origin/main.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-ca06e1] merge: resolve docs/demos README c…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T06:40:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f9df4a86836faff584d71f1d6f0969a6705fa5cc",
          "body": "…I VHS plus dual-auth CLI proof\n\nRe-record machine-tui with truecolor env so Bubble Tea fire palette and the\nOpenSSH auth form are visible; keep machine-dual-auth CLI tape for flag matrix.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-ca06e1] docs(demos): full-color machine TU…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T06:36:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6b6cb999fbb31b7104e4f8dfe1ba52dbda422e6e",
          "body": "…KeyMismatchDetail (classification lives in HopFailureDetail)",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-ca06e1] refactor(remote): drop unused Host…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T06:29:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "549d9dca799d6eb0896afbbb8c905a554c4e4707",
          "body": "…surfaces, tests, and CLI docs\n\nFinish the WI-ca06e1 implementation: auth-aware hop failure formatting,\nlist --remote classified unreachable lines, discover flag-matrix tests,\ndiagnose HINT, FormatHopFailure/AuthModeHint, and regenerated CLI reference.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-ca06e1] feat(machine): complete dual-auth …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T06:20:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a4b7e149dc540bf9444714569179db2f0cca218d",
          "body": "…defaults and hop error classes\n\nDefault discover to OpenSSH (ssh-agent), honor --auth/--user/--identity with\n--discover, classify check-mode/host-key/publickey failures, and expand\ndiagnose with auth labels and copy-paste probe lines (WI-ca06e1 D1–D7).",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-ca06e1] feat(machine): dual-auth discover …",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T06:15:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bde215760250bc6068fbc46a486482bc1dbdcb55",
          "body": "…ual PM) (#480)\n\n## Summary\n\n`--author` was **overcounting actual effort** (summing each repo’s\nfirst→last commit span), which made personal leverage look artificially\nlow (e.g. ~37x vs ~334x campaign) while COCOMO/LOC totals stayed\nidentical.\n\n### Root cause\n- Personal actual PM = Σ(author span per\n[…]\nect campaign\n- [x] Confirm personal `actual_person_months` ≈ campaign actual (not\n~N×)\n- [x] Confirm personal full leverage within ~band of campaign when sole\nmajority author\n- [ ] CI green on this PR",
          "is_bot": false,
          "headline": "fix(leverage): correct personal --author leverage (no multi-count act…",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T02:18:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d5e341ee4e5d1ec17f5e7a6c4b38311913b8fbea",
          "body": "…r edge cases from second review\n\n- Do not invent AuthorIDs for ad-hoc/partial filters (keeps git substring path)\n- Match full display names exactly; keep single-token display match\n- AuthorHasCommits propagates cancel and operational git errors\n- --by-author suppresses configured author_email default (no silent personal mode)\n- Propagate author-presence errors when filtering projects",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-a61e82] fix(leverage): harden author filte…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T02:15:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ccb00810b7ec033d59fd939666a364001bf12aff",
          "body": "…er review findings\n\n- Stop retaining raw --author substring after configured identity match;\n  match IDs/emails by exact local-part (alice ≠ malice)\n- Propagate cancellation and operational git errors from author date queries\n- Make --author and --by-author mutually exclusive\n- Precompute per-git-dir author spans for --by-author (O(repos) not O(authors×repos×emails))\n- Move git-backed coverage to container integration tests; keep unit tests pure",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-a61e82] fix(leverage): address author-filt…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T01:50:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f18174a3474805c230373bb4525372bf371bf507",
          "body": "## Summary\n\n- prevent generic `camp commit`, project commits, and worktree commits\nfrom silently inheriting stale `.campaign/workitems/current.yaml`\ncontext\n- preserve explicit, ancestor, linked-project, and festival context\nresolution\n- keep `camp workitem commit` as the intentional current-workite\n[…]\nh` passed: stable/dev builds, vet, lint, and dev short\ntests\n- targeted resolver, workitem, commit, project, and worktree tests\npassed\n- unrelated dungeon-migration worktree changes were left unstaged",
          "is_bot": false,
          "headline": "fix: prevent stale workitem context in generic commits (#479)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-22T01:20:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ae127d7010663c040460b64fb62168d8c40477c7",
          "body": "… personal actual effort under --author\n\nPersonal mode previously summed each project's author date span, inflating\nactual person-months ~9x on multi-repo campaigns and collapsing leverage\n(e.g. 334x → 37x) while leaving COCOMO estimates unchanged.\n\n- Union author commit spans across unique git dirs\n[…]\nership for --author\n- Expand --author through authors.json email groups\n- Rewrite --by-author as est PM / union actual PM (not weightedPM share)\n- Document personal mode formulas and add unit coverage",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-a61e82] fix(leverage): stop multi-counting…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T23:21:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e214d412faab82e6ff9f3acb9a9991979d5b8759",
          "body": "## Summary\n\n- Make `camp worktrees list` automatically scope to the current\nregistered project.\n- Detect project context from both the main checkout and linked Git\nworktrees.\n- Preserve `--project` as an explicit filter when invoked outside a\nproject.\n- Add a container-backed regression test and a d\n[…]\nree-list-project-aware/docs/demos/worktree-list.gif)\nand the reproducible\n[`worktree-list.tape`](https://github.com/Obedience-Corp/camp/blob/worktree-list-project-aware/docs/demos/worktree-list.tape).",
          "is_bot": false,
          "headline": "fix(worktrees): make list project-aware (#478)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T23:19:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4966f96c7b737eb3443f1b43d4fd3ff2316bc6bf",
          "body": "… context",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-a61e82] fix: prevent stale workitem commit…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T23:01:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f73a6c0dae712e4b06afaa5a4bb6016930d594d5",
          "body": "…m linked worktree match\n\nmatchLinkedWorktree now returns ctx.Err() instead of nil so list scope\ndetection never treats cancellation as a silent campaign-wide fallback.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix(worktrees): propagate context cancel fro…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T22:55:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "71853a08f2f467e6a82858e10a1b559df2cf865d",
          "body": "…Within coverage to container harness\n\nHost TempDir/Symlink unit tests violate the filesystem-mutation policy.\nKeep pure pathWithin tables in unit tests and prove symlink project\nscoping in the container-backed integration suite.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-FE-RM0001] test(worktrees): move symlink path…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T20:52:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c9780cbd10eb0979fad72a1f5554651b63a597af",
          "body": null,
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4] fix: prevent stale workitem commit tags",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T20:37:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "960cf6b81c5a5322424ec0b401c2b64b7b8d111b",
          "body": "…t detection and cut campaign-root cost\n\nShort-circuit campaign root and non-worktree campaign paths so unscoped\nlist no longer double-enumerates git worktrees. Extract match helpers,\nnormalize paths for symlink-stable containment, and unit-test pathWithin\nplus registered-project matching.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-FE-RM0001] fix(worktrees): harden list projec…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T13:51:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "196732a70b16ec2180a0b1dfe40cdc185ac026c2",
          "body": "…rktree tui recording",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-FE-RM0001] docs(demo): preserve full-color wo…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T13:48:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3c507306b22808c8d5c3c33a7ba7420da72189cb",
          "body": "…ui with cgo",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-FE-RM0001] docs(demo): record worktree list t…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T01:16:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3d27e2c90286cde1365fcfad55a4b0c43a451c49",
          "body": "## Summary\n\n`camp fresh` could leave you unable to use `main` on the primary project\npath because a finished worktree still had `main` checked out. Git then\nfails with:\n\n```text\nfatal: 'main' is already used by worktree at '.../worktrees/camp/...'\n```\n\nPreviously fresh worked around this by syncing \n[…]\nh/`\n- [x] `go test -tags=integration -run\nTestFresh_ReclaimsDefaultBranchFromOtherWorktree ./tests/integration/`\n- [x] Smoke: real camp tree with main stuck on a worktree — free +\ncheckout main + pull",
          "is_bot": false,
          "headline": "fix(fresh): reclaim default branch from clean worktrees (#477)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T00:55:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "67532bce4e7818ee2df81313bf661b8e85619f16",
          "body": "…h and lock decision matrix in tests\n\nExtract maybeReclaimDefaultBranch so dry-run and real runs share state\nflips and messaging; pure helpers make the resolve→reclaim matrix easy\nto unit-test without git.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-2f3133] refactor(fresh): share reclaim pat…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T00:50:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4586b068a301cc4ca652535ab805d31b58ee8f91",
          "body": "…ect context",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-2f3133] fix(worktrees): scope list to proj…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T00:27:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7f144ae51e1455a7e3bc57de8c7b5cb7ddb57d0c",
          "body": "… from clean worktrees\n\nWhen main (or the default branch) is stuck on another clean worktree,\ncamp fresh detaches that worktree and checks out the branch on the\nprimary project path instead of failing with git's \"already used by\nworktree\" error or leaving the primary on detached origin/main forever.\n\nDirty occupying worktrees still fall back to detached origin/<default>\nwith a clear skip reason.",
          "is_bot": false,
          "headline": "[obey-campaign:8deed8b4-WI-2f3133] fix(fresh): reclaim default branch…",
          "author_name": "lancekrogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-21T00:10:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "76263ebf34ef8a61c8ec51110420439db17f9081",
          "body": "## Summary\n\n- batch large path lists when resetting the real Git index after scoped\ncommits\n- prevent `camp dungeon migrate` from failing during cleanup on large\ncampaigns\n- add regression coverage for argument-size-safe batching\n\n## Root cause\n\nDungeon migration expands affected directory pathspecs\n[…]\ntests passed\n- stable/dev builds and `go vet` passed\n- `just gate-fast` reached lint; its only failure was the pre-existing\nunused `renderStatusBar` finding in\n`internal/intent/tui/explorer/render.go`",
          "is_bot": false,
          "headline": "fix: handle large dungeon migration commits (#475)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-20T23:44:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0ba3f70fc3acee030a2671cf93df214cc6ad66eb",
          "body": "## Summary\n\n- Project campaign skill bundles into each project worktree\n(`.agents/skills`, `.claude/skills`, and `.grok/skills →\n.agents/skills`) so Grok/Claude sessions whose git root is the worktree\nstill discover `.campaign/skills`.\n- Run projection automatically on `camp project worktree add` (a\n[…]\n”\n- [ ] From that worktree: `grok inspect` lists campaign skills as\n`project`\n- [ ] `camp skills link --worktrees-only` repairs existing worktrees\n- [ ] `camp skills status` shows linked worktree rows",
          "is_bot": false,
          "headline": "feat(skills): project campaign skills into project worktrees (#474)",
          "author_name": "Lance Rogers",
          "author_login": "lancekrogers",
          "committed_at": "2026-07-20T23:44:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        }
      ],
      "releases_count": 27,
      "commits_last_year": 1960,
      "latest_release_at": "2026-07-26T09:36:28Z",
      "latest_release_tag": "v0.3.1",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 28,
      "days_since_latest_release": 1,
      "mean_days_between_releases": 2.9
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 37,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/Obedience-Corp/camp",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/Obedience-Corp/camp",
          "is_deprecated": false,
          "latest_version": "v0.3.1",
          "repository_url": "https://github.com/Obedience-Corp/camp",
          "versions_count": 30,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-26T09:17:32Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 1
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 2,
      "watchers": 0,
      "fork_history": {
        "days": [
          {
            "date": "2026-07-21",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": null,
      "open_issues_and_prs": 17
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "demos"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "justfile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 74083,
      "source_files_sampled": 1368,
      "oversized_source_files": 1,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [
          {
            "name": "github.com/klauspost/compress",
            "direct": false,
            "version": "v1.18.5",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5841"
            ],
            "fixed_version": "1.18.7",
            "advisory_count": 1,
            "oldest_advisory_days": 0
          },
          {
            "name": "github.com/yuin/goldmark",
            "direct": false,
            "version": "v1.7.16",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5320"
            ],
            "fixed_version": "1.7.17",
            "advisory_count": 1,
            "oldest_advisory_days": 20
          },
          {
            "name": "golang.org/x/crypto",
            "direct": false,
            "version": "v0.54.0",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5932"
            ],
            "fixed_version": null,
            "advisory_count": 1,
            "oldest_advisory_days": 20
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "unknown": 3
        },
        "advisory_count": 3,
        "affected_count": 3,
        "assessed_count": 106,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/Obedience-Corp/obey-shared",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.4.5"
        },
        {
          "name": "github.com/alecthomas/chroma/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.23.1"
        },
        {
          "name": "github.com/charmbracelet/bubbles",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.0"
        },
        {
          "name": "github.com/charmbracelet/bubbletea",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.3.10"
        },
        {
          "name": "github.com/charmbracelet/glamour",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.10.0"
        },
        {
          "name": "github.com/charmbracelet/huh",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.8.0"
        },
        {
          "name": "github.com/charmbracelet/lipgloss",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.1-0.20250404203927-76690c660834"
        },
        {
          "name": "github.com/creack/pty",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.24"
        },
        {
          "name": "github.com/google/uuid",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.6.0"
        },
        {
          "name": "github.com/ktr0731/go-fuzzyfinder",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.9.0"
        },
        {
          "name": "github.com/lancekrogers/guild-scaffold",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.1.0"
        },
        {
          "name": "github.com/moby/patternmatcher",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.6.1"
        },
        {
          "name": "github.com/muesli/termenv",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.16.0"
        },
        {
          "name": "github.com/sahilm/fuzzy",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.1.1"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.2"
        },
        {
          "name": "github.com/spf13/pflag",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.10"
        },
        {
          "name": "github.com/stretchr/testify",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.11.1"
        },
        {
          "name": "github.com/testcontainers/testcontainers-go",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.42.0"
        },
        {
          "name": "golang.org/x/sys",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.47.0"
        },
        {
          "name": "golang.org/x/term",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.45.0"
        },
        {
          "name": "gopkg.in/yaml.v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "github.com/alecthomas/chroma/v2",
            "direct": true,
            "version": "v2.23.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/bubbles",
            "direct": true,
            "version": "v1.0.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/bubbletea",
            "direct": true,
            "version": "v1.3.10",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/glamour",
            "direct": true,
            "version": "v0.10.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/huh",
            "direct": true,
            "version": "v0.8.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/lipgloss",
            "direct": true,
            "version": "v1.1.1-0.20250404203927-76690c660834",
            "ecosystem": "go"
          },
          {
            "name": "github.com/creack/pty",
            "direct": true,
            "version": "v1.1.24",
            "ecosystem": "go"
          },
          {
            "name": "github.com/google/uuid",
            "direct": true,
            "version": "v1.6.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/ktr0731/go-fuzzyfinder",
            "direct": true,
            "version": "v0.9.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lancekrogers/guild-scaffold",
            "direct": true,
            "version": "v0.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/patternmatcher",
            "direct": true,
            "version": "v0.6.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/muesli/termenv",
            "direct": true,
            "version": "v0.16.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/obedience-corp/obey-shared",
            "direct": true,
            "version": "v0.4.5",
            "ecosystem": "go"
          },
          {
            "name": "github.com/sahilm/fuzzy",
            "direct": true,
            "version": "v0.1.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/spf13/cobra",
            "direct": true,
            "version": "v1.10.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/spf13/pflag",
            "direct": true,
            "version": "v1.0.10",
            "ecosystem": "go"
          },
          {
            "name": "github.com/stretchr/testify",
            "direct": true,
            "version": "v1.11.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/testcontainers/testcontainers-go",
            "direct": true,
            "version": "v0.42.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/sys",
            "direct": true,
            "version": "v0.47.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/term",
            "direct": true,
            "version": "v0.45.0",
            "ecosystem": "go"
          },
          {
            "name": "gopkg.in/yaml.v3",
            "direct": true,
            "version": "v3.0.1",
            "ecosystem": "go"
          },
          {
            "name": "dario.cat/mergo",
            "direct": false,
            "version": "v1.0.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/atotto/clipboard",
            "direct": false,
            "version": "v0.1.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/aymanbagabas/go-osc52/v2",
            "direct": false,
            "version": "v2.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/aymerick/douceur",
            "direct": false,
            "version": "v0.2.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/azure/go-ansiterm",
            "direct": false,
            "version": "v0.0.0-20250102033503-faa5f7b0171c",
            "ecosystem": "go"
          },
          {
            "name": "github.com/catppuccin/go",
            "direct": false,
            "version": "v0.3.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/cenkalti/backoff/v4",
            "direct": false,
            "version": "v4.3.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/cespare/xxhash/v2",
            "direct": false,
            "version": "v2.3.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/colorprofile",
            "direct": false,
            "version": "v0.4.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/x/ansi",
            "direct": false,
            "version": "v0.11.6",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/x/cellbuf",
            "direct": false,
            "version": "v0.0.15",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/x/exp/slice",
            "direct": false,
            "version": "v0.0.0-20260301212224-50d5c240f29a",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/x/exp/strings",
            "direct": false,
            "version": "v0.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/x/term",
            "direct": false,
            "version": "v0.2.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/clipperhouse/displaywidth",
            "direct": false,
            "version": "v0.11.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/clipperhouse/uax29/v2",
            "direct": false,
            "version": "v2.7.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/containerd/errdefs",
            "direct": false,
            "version": "v1.0.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/containerd/errdefs/pkg",
            "direct": false,
            "version": "v0.3.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/containerd/log",
            "direct": false,
            "version": "v0.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/containerd/platforms",
            "direct": false,
            "version": "v0.2.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/cpuguy83/dockercfg",
            "direct": false,
            "version": "v0.3.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/cpuguy83/go-md2man/v2",
            "direct": false,
            "version": "v2.0.7",
            "ecosystem": "go"
          },
          {
            "name": "github.com/davecgh/go-spew",
            "direct": false,
            "version": "v1.1.2-0.20180830191138-d8f796af33cc",
            "ecosystem": "go"
          },
          {
            "name": "github.com/distribution/reference",
            "direct": false,
            "version": "v0.6.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/dlclark/regexp2",
            "direct": false,
            "version": "v1.11.5",
            "ecosystem": "go"
          },
          {
            "name": "github.com/docker/go-connections",
            "direct": false,
            "version": "v0.6.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/docker/go-units",
            "direct": false,
            "version": "v0.5.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/dustin/go-humanize",
            "direct": false,
            "version": "v1.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/ebitengine/purego",
            "direct": false,
            "version": "v0.10.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/erikgeiser/coninput",
            "direct": false,
            "version": "v0.0.0-20211004153227-1c3628e74d0f",
            "ecosystem": "go"
          },
          {
            "name": "github.com/felixge/httpsnoop",
            "direct": false,
            "version": "v1.0.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gdamore/encoding",
            "direct": false,
            "version": "v1.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gdamore/tcell/v2",
            "direct": false,
            "version": "v2.13.8",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-logr/logr",
            "direct": false,
            "version": "v1.4.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-logr/stdr",
            "direct": false,
            "version": "v1.2.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-ole/go-ole",
            "direct": false,
            "version": "v1.2.6",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gorilla/css",
            "direct": false,
            "version": "v1.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/inconshreveable/mousetrap",
            "direct": false,
            "version": "v1.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/klauspost/compress",
            "direct": false,
            "version": "v1.18.5",
            "ecosystem": "go"
          },
          {
            "name": "github.com/ktr0731/go-ansisgr",
            "direct": false,
            "version": "v0.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lucasb-eyer/go-colorful",
            "direct": false,
            "version": "v1.3.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lufia/plan9stats",
            "direct": false,
            "version": "v0.0.0-20211012122336-39d0f177ccd0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/magiconair/properties",
            "direct": false,
            "version": "v1.8.10",
            "ecosystem": "go"
          },
          {
            "name": "github.com/mattn/go-isatty",
            "direct": false,
            "version": "v0.0.20",
            "ecosystem": "go"
          },
          {
            "name": "github.com/mattn/go-localereader",
            "direct": false,
            "version": "v0.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/mattn/go-runewidth",
            "direct": false,
            "version": "v0.0.20",
            "ecosystem": "go"
          },
          {
            "name": "github.com/microcosm-cc/bluemonday",
            "direct": false,
            "version": "v1.0.27",
            "ecosystem": "go"
          },
          {
            "name": "github.com/microsoft/go-winio",
            "direct": false,
            "version": "v0.6.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/mitchellh/hashstructure/v2",
            "direct": false,
            "version": "v2.0.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/docker-image-spec",
            "direct": false,
            "version": "v1.3.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/go-archive",
            "direct": false,
            "version": "v0.2.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/moby/api",
            "direct": false,
            "version": "v1.54.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/moby/client",
            "direct": false,
            "version": "v0.4.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/sys/sequential",
            "direct": false,
            "version": "v0.6.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/sys/user",
            "direct": false,
            "version": "v0.4.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/sys/userns",
            "direct": false,
            "version": "v0.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/term",
            "direct": false,
            "version": "v0.5.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/muesli/ansi",
            "direct": false,
            "version": "v0.0.0-20230316100256-276c6243b2f6",
            "ecosystem": "go"
          },
          {
            "name": "github.com/muesli/cancelreader",
            "direct": false,
            "version": "v0.2.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/muesli/reflow",
            "direct": false,
            "version": "v0.3.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/nsf/termbox-go",
            "direct": false,
            "version": "v1.1.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/opencontainers/go-digest",
            "direct": false,
            "version": "v1.0.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/opencontainers/image-spec",
            "direct": false,
            "version": "v1.1.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/pkg/errors",
            "direct": false,
            "version": "v0.9.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/pmezard/go-difflib",
            "direct": false,
            "version": "v1.0.1-0.20181226105442-5d4384ee4fb2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/power-devops/perfstat",
            "direct": false,
            "version": "v0.0.0-20240221224432-82ca36839d55",
            "ecosystem": "go"
          },
          {
            "name": "github.com/rivo/uniseg",
            "direct": false,
            "version": "v0.4.7",
            "ecosystem": "go"
          },
          {
            "name": "github.com/russross/blackfriday/v2",
            "direct": false,
            "version": "v2.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/shirou/gopsutil/v4",
            "direct": false,
            "version": "v4.26.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/sirupsen/logrus",
            "direct": false,
            "version": "v1.9.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/tklauser/go-sysconf",
            "direct": false,
            "version": "v0.3.16",
            "ecosystem": "go"
          },
          {
            "name": "github.com/tklauser/numcpus",
            "direct": false,
            "version": "v0.11.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/xo/terminfo",
            "direct": false,
            "version": "v0.0.0-20220910002029-abceb7e1c41e",
            "ecosystem": "go"
          },
          {
            "name": "github.com/yuin/goldmark",
            "direct": false,
            "version": "v1.7.16",
            "ecosystem": "go"
          },
          {
            "name": "github.com/yuin/goldmark-emoji",
            "direct": false,
            "version": "v1.0.6",
            "ecosystem": "go"
          },
          {
            "name": "github.com/yusufpapurcu/wmi",
            "direct": false,
            "version": "v1.2.4",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/auto/sdk",
            "direct": false,
            "version": "v1.2.1",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
            "direct": false,
            "version": "v0.60.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel",
            "direct": false,
            "version": "v1.42.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel/metric",
            "direct": false,
            "version": "v1.42.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel/trace",
            "direct": false,
            "version": "v1.42.0",
            "ecosystem": "go"
          },
          {
            "name": "go.yaml.in/yaml/v3",
            "direct": false,
            "version": "v3.0.4",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/crypto",
            "direct": false,
            "version": "v0.54.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/net",
            "direct": false,
            "version": "v0.56.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/text",
            "direct": false,
            "version": "v0.40.0",
            "ecosystem": "go"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 106,
        "direct_count": 21,
        "indirect_count": 85
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 8,
        "merged_prs": 441,
        "open_issues": 9,
        "closed_ratio": 0.812,
        "closed_issues": 39,
        "closed_unmerged_prs": 16
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "lancekrogers",
          "commits": 1958,
          "avatar_url": "https://avatars.githubusercontent.com/u/12162551?v=4"
        },
        {
          "type": "User",
          "login": "obey-agent",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/265918629?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.999
    },
    "quality_signals": {
      "has_ci": false,
      "has_tests": true,
      "ci_workflows": [],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "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": 0,
            "reason": "0 out of 11 merged PRs checked by a CI test -- score normalized to 0",
            "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": 3,
            "reason": "Found 4/12 approved changesets -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 4 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "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": 9,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": null,
            "reason": "no dependencies found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "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": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 7,
            "reason": "3 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "43e1d4772a530536d5bed1b0d95226dda48d8eae",
        "ran_at": "2026-07-28T05:14:43Z",
        "aggregate_score": 5,
        "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-28T03:31:00Z",
      "oldest_open_prs": [
        {
          "number": 504,
          "created_at": "2026-07-26T11:04:14Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 505,
          "created_at": "2026-07-26T11:19:15Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 506,
          "created_at": "2026-07-26T11:24:41Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 507,
          "created_at": "2026-07-26T11:39:50Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 508,
          "created_at": "2026-07-26T11:58:14Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 509,
          "created_at": "2026-07-26T12:03:51Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 511,
          "created_at": "2026-07-26T22:44:51Z",
          "last_comment_at": "2026-07-26T22:46:27Z",
          "last_comment_author": "obey-agent"
        },
        {
          "number": 515,
          "created_at": "2026-07-27T21:56:47Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-28T03:30:58Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": [
        {
          "number": 221,
          "created_at": "2026-04-16T00:25:19Z",
          "last_comment_at": "2026-07-19T05:21:17Z",
          "last_comment_author": "lancekrogers"
        },
        {
          "number": 245,
          "created_at": "2026-04-19T05:35:07Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 284,
          "created_at": "2026-05-13T11:27:09Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 306,
          "created_at": "2026-05-25T18:21:08Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 307,
          "created_at": "2026-05-25T19:55:39Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 316,
          "created_at": "2026-06-02T04:05:04Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 317,
          "created_at": "2026-06-03T07:52:16Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 335,
          "created_at": "2026-06-17T03:07:07Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 513,
          "created_at": "2026-07-26T22:45:49Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/Obedience-Corp/camp",
    "host": "github.com",
    "name": "camp",
    "owner": "Obedience-Corp"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 57,
      "inputs": {
        "security": 59,
        "vitality": 90,
        "community": 21,
        "governance": 58,
        "engineering": 50
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 90,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 83,
            "inputs": {
              "commits_last_year": 1960,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 28
            },
            "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": "28/52 weeks with commits",
                "points": 19.4,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 28
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "1960 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 1960
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 27,
              "latest_release_tag": "v0.3.1",
              "releases_from_tags": false,
              "days_since_latest_release": 1,
              "mean_days_between_releases": 2.9
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "27 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 27
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~2.9 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 2.9
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 0,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 0 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 21,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 1,
              "stars": 2,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "2 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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": "at_risk",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 44,
            "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": "license file present, not a recognized license",
                "points": 16.9,
                "status": "partial",
                "details": [
                  {
                    "code": "license_custom",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 58,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 22,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.999
            },
            "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": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "2 contributors",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 4 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 79,
            "inputs": {
              "merged_prs": 441,
              "open_issues": 9,
              "closed_issues": 39,
              "issue_closed_ratio": 0.812,
              "closed_unmerged_prs": 16
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "81% of issues closed",
                "points": 38,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 81
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "441/457 decided PRs merged",
                "points": 36.9,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 441,
                      "decided": 457
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 4/12 approved changesets -- score normalized to 3",
                "points": 4.5,
                "status": "partial",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 45,
            "inputs": {
              "followers": 6,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "Obedience-Corp",
              "public_repos": 11,
              "account_age_days": 254
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "6 followers of Obedience-Corp",
                "points": 6.1,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 6,
                      "login": "Obedience-Corp"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "11 public repos, account ~0 yr old",
                "points": 9.2,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 11
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 0
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/Obedience-Corp/camp"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 1
            },
            "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 1 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "30 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 30
                    }
                  }
                ],
                "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": "moderate",
        "name": "Engineering Quality",
        "value": 50,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "critical",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 24,
            "inputs": {
              "has_ci": false,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "0 out of 11 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "topics": [
                "ai",
                "ai-agents",
                "ai-tools",
                "ai-workflow",
                "ai-workspace",
                "fest",
                "festival-methodology",
                "monorepo",
                "navigation",
                "claude-code",
                "codex",
                "git",
                "opencode",
                "cli",
                "context-engineering",
                "developer-tools",
                "golang",
                "project-management"
              ],
              "has_wiki": false,
              "homepage": "https://docs.fest.build",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://docs.fest.build",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "18 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 18
                    }
                  }
                ],
                "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": "moderate",
        "name": "Security",
        "value": 59,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dangerous-Workflow, Packaging, Pinned-Dependencies, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dangerous_workflow",
                    "packaging",
                    "pinned_dependencies",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 49,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 13,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 5,
              "scorecard_aggregate": 5
            },
            "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": "0 out of 11 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "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 4/12 approved changesets -- score normalized to 3",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 4 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "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.2,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "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": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "3 existing vulnerabilities detected",
                "points": 5.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories, No advisories left outstanding. Remaining weights renormalized. Matched 106 resolved dependencies against OSV. This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "indirect_dependencies_free_of_known_advisories",
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 106
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 3,
              "affected_packages": 3,
              "assessed_packages": 106,
              "unassessed_packages": 0,
              "affected_by_severity": "unknown 3",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "transitive set not separable from development and test dependencies in this scope",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_scope_not_separable",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 106,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 5
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 60,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.78,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "78 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 78,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_pinned_dependencies"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 68,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "justfile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "justfile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "justfile"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 74083,
              "source_files_sampled": 1368,
              "oversized_source_files": 1
            },
            "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": "1/1368 source files over 60KB",
                "points": 55,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 1368,
                      "oversized": 1
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "demos"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "demos",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "demos"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-28T05:15:00.682027Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/o/Obedience-Corp/camp.svg",
  "full_name": "Obedience-Corp/camp",
  "license_state": "custom",
  "license_spdx": null
}

评分是信号,而非担保。 评分反映的是 GitHub 上公开可见的实践——不是代码审计,也不是安全保证。

缺失数据将被剔除并重新归一化权重,绝不按零分计。方法论已版本化并公开:指标 v1.13.0、模式 v0.27.0—— 完整方法论 · 指标知识库.

单项结果在整体记录中的位置: 汇总统计Go.