docops upgrade + update-check + read-side commands (TP-011/012/018/020/021)#1
Merged
Conversation
Ships the four CLI query commands defined in ADR-0018. Agents can now retrieve a focused slice of the index without loading the full .index.json: look up one doc (get), filter/sort the listing (list), walk typed edges (graph), or get a prioritised task recommendation (next). Shared bootstrap extracted to bootstrap.go. 27 new tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ships docops search with text match (title > tags > body ranking), structured filters (--kind/--status/--coverage/--tag/--priority/ --assignee/--since), --regex and --case flags, and --json output. Also returns root from bootstrapIndex (used by search for lazy body reads). 20 new tests including a dog-food pass against the live repo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rader + update-check ADR-0023 captures the gstack-shaped update-check pattern: cached probe of remote VERSION, fail-quiet on network errors, hooked into upgrade so users learn before syncing stale templates. TP-020 carves out the internal/scaffold/ refactor as a standalone, behavior-preserving step so TP-018 (upgrader) only diffs the genuinely new code. TP-021 owns the update-check implementation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move the helpers TP-018's upgrader will need to share with init into a new internal/scaffold/ package: Action, the AGENTS.md block markers, MergeAgentsBlock/ExtractBlock, DirAction/FileAction, Execute, PrintPlan, and a LoadShippedSkills wrapper around templates.Skills(). initter.go shrinks from 429 to ~225 lines and re-imports from scaffold; the public Run/Options/Result surface is unchanged (Action stays available via a type alias). Tests cover the moved helpers directly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New internal/updatecheck/ package implements the gstack-shaped pattern: cache last-update-check under ~/.docops/ with split TTLs (6h up-to-date, 24h upgrade-available), fetch from raw.githubusercontent.com/.../VERSION with a 5s timeout, fail quiet on every transient error so docops never blocks a commit hook. Snooze file with escalating windows (24h/48h/7d) keeps reminders bounded. Skips entirely on dev builds, +dirty trees, and DOCOPS_UPDATE_CHECK=off. Standalone subcommand `docops update-check` prints UP_TO_DATE / UPGRADE_AVAILABLE on one line (or nothing when skipped) so users and shell hooks can script around it. --force bypasses cache, --snooze records a snooze for the current available remote, --json emits structured output. VERSION file at the repo root (initially 0.1.1) is the upstream source of truth; release-time bumps land alongside the git tag. The upgrade integration (warn before in-place sync when binary is behind) ships with TP-018. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the in-band upgrade path specified by ADR-0021. After brew/scoop bumps the binary, `docops upgrade` syncs the shipped skills, schemas, and the AGENTS.md docops block in place — no clobbering of docops.yaml or the pre-commit hook unless the user opts in via --config or --hook. Removed-skill deletion is scoped to the .claude/skills/docops/ and .cursor/commands/docops/ subdirectories. A .docops-manifest sentinel written on first successful run lets subsequent upgrades distinguish "shipped removal" from "user added a custom skill"; the latter trips a refusal (exit 2) so user files are never silently deleted. Wires update-check (TP-021) into the upgrade pre-flight: a stale binary triggers a warning + interactive prompt before any sync runs, so users do not ship the older templates after forgetting to brew upgrade. --yes / non-TTY stdin proceed silently. cmd_upgrade ships --dry-run, --yes/-y, --config, --hook, --json with the action vocabulary promised by ADR-0021 (new, refreshed, removed, up-to-date, block-refreshed). scaffold gains KindRemove + Execute support. New internal/upgrader/ package + tests + cmd-level tests + templates/skills/docops/upgrade.md + README "Upgrading" subsection + AGENTS.md.tmpl mention + skills lint update. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Captures the decision to write both CLAUDE.md and AGENTS.md from docops init/upgrade, sharing the same docops-managed block. Closes the gap where Claude Code reads CLAUDE.md by default and never sees the docops invariants. Smaller change than gstack's host-rewrite approach; no symlink portability risk. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both files now carry the same docops block so Claude Code (which reads CLAUDE.md by default) and other agents (which read AGENTS.md) see the same project-state invariants. init writes both; upgrade refreshes both and creates either one if absent — so v0.1.x users gain CLAUDE.md on first post-ADR-0024 upgrade. Existing planAgents helpers in initter and upgrader are generalized to planMarkdownBlock(rel, tmpl) and called twice (once per file). A new templates-package test asserts byte-identical docops blocks between AGENTS.md.tmpl and CLAUDE.md.tmpl so future template authors catch drift at build time. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New 'make release VERSION=X.Y.Z' target validates the version, bumps the VERSION file, commits, tags annotated, and pushes both — replacing the manual "edit VERSION, commit, tag, push" sequence with one command. Refuses on a dirty tree, off-main branch, or pre-existing tag. DRY_RUN=1 prints what would happen without writing. Release workflow gains a guard step that fails the run if the pushed tag does not match the VERSION file body. Catches the easy mistake of tagging manually without bumping VERSION (which would silently break docops update-check for users on the previous release, since the file is what raw.githubusercontent.com serves). README "Release" section updated to describe the new flow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
git status --porcelain treats untracked files as dirty; the docops binary often sits at the repo root after a smoke test and would spuriously block a release. diff-index --quiet HEAD only reports modifications to tracked files, which is what we actually need. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ships the in-band upgrade path for projects already initialized with docops, plus a gstack-shaped update probe so users learn when their binary is stale, plus CLAUDE.md support so Claude Code reads the docops invariants by default, plus the four read-side commands that landed earlier on
dev.docops upgrade: refresh DocOps-owned scaffolding (skills, schemas, AGENTS.md/CLAUDE.md blocks) without clobberingdocops.yamlor the pre-commit hook. Opt-in--config/--hookfor the customizable bits. Manifest safety belt (.docops-manifest) refuses to silently delete user-added files inside the docops-owned subdirs on subsequent runs.docops update-check: cached probe of upstreamVERSION, fail-quiet on transient errors, 6h/24h split TTLs, snooze with escalating windows, dev-build /DOCOPS_UPDATE_CHECK=offskips. Wired intodocops upgradeas a pre-flight warning so you cannot accidentally sync the older templates.CLAUDE.mdalongsideAGENTS.md: both files share the same docops block.initwrites both;upgraderefreshes both and creates either one if absent, so v0.1.x users gainCLAUDE.mdon first post-ADR-0024 upgrade. A templates-sync test catches block drift at build time. Closes the gap where Claude Code readsCLAUDE.mdby default and never saw the docops invariants.internal/scaffold/frominternal/initter/so upgrader and initter share helpers. No behavior change forinit.docops search,docops get,docops list,docops graph,docops next(already ondev, included in this PR).Planning artifacts: ADR-0023 (update-check), ADR-0024 (CLAUDE.md), TP-020/021/022.
New CLI surface
docops upgradeoutput uses the sigils promised by ADR-0021:+ new,~ refreshed,- removed,= up-to-date,~ block-refreshed.Files of note
internal/scaffold/— shared planner helpers (new package)internal/upgrader/— TP-018 implementation + manifest safety beltinternal/updatecheck/— TP-021 implementationcmd/docops/cmd_upgrade.go,cmd/docops/cmd_update_check.go— CLI surfacetemplates/CLAUDE.md.tmpl— new sibling of AGENTS.md.tmpl, shared docops blocktemplates/agents_claude_block_sync_test.go— fails the build if the two block bodies drifttemplates/skills/docops/upgrade.md— shipped skillVERSION— upstream source of truth (initially0.1.1); release-time bump documented but not yet automated in goreleaserREADME.md— new "Upgrading an existing project" subsectiontemplates/AGENTS.md.tmpl— addsupgradeandupdate-checkto the CLI list, footer mentions CLAUDE.md siblingTest plan
go test ./...— all packages green (15 pkgs)internal/upgrader/upgrader_test.go— fresh idempotent run, add+refresh+remove cycle, --config / --hook gating, first-run vs subsequent-run safety belt, AGENTS.md and CLAUDE.md block refresh, CLAUDE.md created when absent, dry-run writes nothinginternal/updatecheck/updatecheck_test.go— cache hit (UP_TO_DATE / UPGRADE_AVAILABLE) skips network, stale cache refetches, network error → up-to-date, invalid-response cases, dev-build skip, env opt-out, snooze suppression + version-bump invalidation + expiry, --force bypasscmd/docops/cmd_upgrade_test.go,cmd/docops/cmd_update_check_test.go— CLI exit codes, JSON shape, --yes flowinternal/scaffold/scaffold_test.go— direct coverage for moved helperstemplates/agents_claude_block_sync_test.go— block bodies stay byte-identical across the two templates/tmpwithinit --yes, both AGENTS.md and CLAUDE.md present; delete CLAUDE.md, runupgrade --yes, CLAUDE.md restored from templatedocops upgrade --dry-runagainst this repo: identifies real drift correctly (refresh several skills, addrefresh.md+upgrade.md, removenext.md, refresh AGENTS.md block, create CLAUDE.md) — left as a separate refresh step for a later commitFollow-ups (not in this PR)
VERSIONfrom the git tag at release timedocops upgrade --yesagainst this repo to sync its own scaffolding (will create a CLAUDE.md for the docops repo itself)backlogto done🤖 Generated with Claude Code