Repository navigation
Releases
devagent 1.0.0
First tagged release, cut at go-public (#463, #464). Everything in this section
had already shipped SHA-by-SHA to master before the tag existed.
-
The plugin carries a version:
plugin.jsonversion: 1.0.0(#532
re-take). Behavior change for every install from the GitHub marketplace,
stated here because #532 required it never be claimed as "no change": until
nowclaude plugin update devagent@devagentfollowedmastercommit by
commit; from this release it resolves to the version string and only sees an
update when that string changes, so a merge tomasterreaches installed
users at the next release rather than immediately. A marketplace added from
a local checkout loads it in place and is not pinned. Measured on Claude Code
2.1.223:claude plugin validate --strictnow passes (it was
documented-red on the missing version), andclaude plugin tag --dry-run
resolvesdevagent--v1.0.0.tests/test_plugin_versioning.pyinverts from
"no version anywhere" to "semver in plugin.json, none in the marketplace
entry, matching CHANGELOG section", andtests/plugin-validate.batswires
the strict gate plus the tag dry-run. README, the docs-site install page and
SECURITY.md describe the release policy instead of SHA-tracking. -
The onboarding site can be built and published (#465).
scripts/build-docs-site.shrenders thedocs-site/pages to a static
site with pandoc, straight from the tracked markdown — no rendered copy is
committed. It rewrites page-to-page links, sends links that leave
docs-site/to the forge, and fails the build on a link it cannot classify
or that resolves to nothing, and refuses a pandoc older than 3.x. A new
publish docs siteworkflow runs the builder's tests, builds, and can deploy
to GitHub Pages by keyless OIDC. Deploy is off until the repository
variableDOCS_SITE_DEPLOYis set totrue, because GitHub Pages is not
enabled on the repository yet and a deploy against a Pages-disabled repo
fails;docs/pages-deployment.mdhas the switch-on steps. New optional test
prerequisite: pandoc 3.x, fortests/build-docs-site.batsonly. -
The oneshot tier's no-repo-diff boundary is enforced mechanically (#595).
"An operational action, not a repo change" lived in prose in three documents
and nothing caught a one-shot that quietly produced commits. The oneshot tier
has no branch step, so nobaseline_shaexists andzero_diff_classify
answeredindeterminateforever. What a branchless tier measures is now
defined as whether the source tree carries unpublished change — on the
base branch, no commits beyonddefault_baseline, no uncommitted paths —
rather than whether the issue itself produced a diff, which a shared source
tree cannot attribute. A newscripts/oneshot-zerodiff.showns the
predicate: it calls the sharedzero_diff_classifyunchanged for the commits
half, adds agit status --porcelainprobe for the dirty half (a dirty-only
tree classifies asempty), compares the checked-out branch to the base, and
mints one exit code per verdict.cleanup.shreads the tier itself and
refuses before any side effect onviolatedorindeterminate, directing
the operator torevise.sh --retier standard; every other tier pays one
header read and never spawns the checker. A shared tree left on a sibling
issue's branch is the routineindeterminate, with a one-line remedy; a
recorded linked worktree isindeterminatewith a remedy that names the
tier. The refusal never asserts authorship.
echo "<reason>" > <issue-dir>/.devagent-oneshot-ackis an auditable escape
seam for trees git cannot measure.
commands/document.md's straggler instruction — which told a oneshot to
commit and promised a step 12 that tier does not have — is carved out, and
commands/implement.md's "must produce no repo diff" is reframed to the
decidable form; both key on the tier name, since the research tier omits
step 12 too. -
Untracked new source files enter the analyzer's changed-line scope (#591).
static_analysis_diff.pyscoped fromgit diffalone, which lists TRACKED
changes only — a brand-new file that had never beengit add-ed produced no
hunks, so every per-file tool skipped it and step 13 passed vacuously for exactly
the file with the least review history. A newget_untracked_ranges()enumerates
untracked, non-ignored candidates with
git ls-files --others --exclude-standard --full-name -z(read-only — no
git add, nogit add -N, no temp commit) and gives each a whole-file
LineRange(1, <line count>), so cpplint, codespell, ruff, flake8, bandit, mypy
and cmake-lint run on it andfilter_novelcounts every line as changed; markdown
runs print one artifact-visible progress line,
Untracked files (whole-file scope): …(stderr under--json, #119), and the
summary labels now say "changed lines or untracked files". The compile-database
tools (cppcheck, clang-tidy, iwyu, compiler warnings) andgit clang-format
cannot reach a file the build / index does not know and still report it clean —
a documented limit. Candidates are limited to the suffixes therun_*filters
already select on (.cc .c .h .py .cmake CMakeLists.txt) and exclude the
analyzer's ownbuild_dir/-asan/-ubsan/-tsandirs and any root-level
build-*dir — whereanalyze-sanitizers.shbuilds regardless of the configured
build_dir(#324/#351) — which a target project's.gitignoremay not cover.
Names are decoded as UTF-8 (never the locale's encoding), and a listed candidate
that cannot be read is named on the same artifact-visible stream instead of
vanishing.scripts/analyze-shellcheck.shgets the same treatment for
*.sh/*.bats/*.bash(both itsgit diffand itsgit ls-filesrun with
core.quotePath=false, so a non-ASCII name — tracked or untracked — is not
silently dropped), keyed on untrackedness so a tracked file
whose only hunks are pure deletions keeps its empty range, with an
untracked (whole-file scope):header line in its artifact. A--filesrun
never widens beyond its pathspecs,.gitignored files stay out, and a
tracked-only tree's output is byte-identical to before. -
run-suite.sh runs bats test files in parallel for a project that opts in
(#593). New[project.<name>]keysuite_jobs(integer ≥ 1, default 1 =
serial) passes--jobs N --no-parallelize-within-filesto bats; tests inside
one file still run in order, matching the file-granularity safety audit in
Issue-593's analysis dir.DEVAGENT_SUITE_JOBSoverrides it for one run and
is scrubbed from both suite children (and unset per test by
tests/lib/hermetic-env.bash), so a test that invokes the runner cannot
inherit it. Scrubbed alongside it:BATS_NUMBER_OF_PARALLEL_JOBSand
BATS_NO_PARALLELIZE_ACROSS_FILES, which bats reads from the environment, so
an inherited value would make the newbats_jobs:line false in either
direction; andBATS_PARALLEL_BINARY_NAME, which would otherwise let bats
reach for a binary the probe below never checked. The value is validated
before either suite runs; N > 1 first checks for GNU parallel by banner (bats
1.10.0's own probe is miswired — an absent binary surfaced inside the TAP
stream as a "truncated" suite) and dies naming the package and the
suite_jobs = 1seam. The artifact gains a
trailingbats_jobs: <N> | (none)line. Carriers: README "Running the test
suite",tests/README.md"Parallel execution", the config skeleton,
docs-site/configuration.md, the spec's run-suite section, and the
core-draft-mr skill's artifact-read note. -
The rederive prober compares the checkout to its baseline and resolves bare
basenames (#590).scripts/rederive.shnow opens its artifact with a
## Checkout vs baselineline —behind N, ahead Magainstdefault_baseline
after a best-effort fetch whose outcome (ok/skipped/FAILED/n/a)
is stamped on the line. Pre-branch,behind > 0is a✗ … STALE CHECKOUT
falsified premise whose remedy names themerge --ff-onlyto run (Issue-570
ran draft through improve three commits behind its base with every file probe
✓); on the recorded issue branch (every revision re-runs draft) the same
numbers print as anℹrow — expected drift, not a premise. An unconfigured
or unresolvable base prints an explicit? behind-count undeterminedline,
never a silent 0; a faultingrev-parse/rev-list/ls-treedies loud. A
.devagent-baselinemarker is acknowledged by existence in the heading and
never parsed (onlybranch.shreads it). A backticked bare basename or path
suffix (SKILL.md,capture/capture.sh) is matched against the HEAD tree by
exact suffix at a/boundary: one hit →✓ tok → path (resolved …)and the
resolved path feeds the since-log and thefile:linedrift check; several →
a~ … ambiguousadvisory row; none → the same✗as before (Issue-570's
artifact carried six ✗ rows, zero real). Plumbing:upstream_fetchsets
UPSTREAM_FETCH_STATUS(skipped|ok|failed) and runs its fetch with
GIT_TERMINAL_PROMPT=0, so git's own credential prompt fails instead of
hanging an unattended step (ship and mergetoall inherit that; an ssh prompt or
a black-holed remote is not covered — a fetch timeout is a recorded
follow-up). The prober measures the issue's recorded worktree when
use_worktreeput the branch there (#571'sactive_tree_resolve), else
source_dir. Carriers:
commands/draft.md, the imPlan template's Preconditions note,core-scope
question 7, and thecommands/branch.mdoverride rules describe the new rows. -
The checklist writers fail closed (#589).
checklist_markrefuses a
name-less mark of a step number that is absent from the ACTIVE## Revision
block but present in an older one — the write used to fall th...