Repository navigation
Releases: llopresto87/Cypress
Release list
v8.2.0
8.2.0 — a harvest folded back into the seed (2026-10-14)
This release comes from a harvest: what grown plants learned, made generic
and folded back into the seed. The seed now needs Python 3.14 and says so at
install time. Graft and grow commit the plant before they write. A team can
keep its own AGENTS.md. Generic skill pages reach a plant when its work
needs them, and every agent runs its own route. The corpora gain library,
tool, skill and legal pages. Project names that earlier records carried are
recast generically; the disclosure is below.
Python 3.14
- The seed's minimum Python is 3.14, and SPEC-0005 §5 is the one home of
that figure. Every script the installer places and every hook it wires
runs on it. install.shruns onpython3when it is at 3.14 or newer, else on the
firstpython3.<n>at or above it onPATH, and writes that name into
every hook command, the Prime Agent extensions included. With none on
PATHit refuses before writing anything, with the fix in one line. When
python3itself is older, a NEXT STEP says so, because agent sessions run
the graph tools aspython3 docs/graph/<tool>.py.install.sh --checkruns each wired hook on the interpreter the hook
names. The CI gate runs on Python 3.14, andtests/test-tool-help.sh
holds the installer'sPYTHON_FLOOR, the spec line and the CI version
equal.
The installer
- A run that made backups ends with a BACKUPS block: every installer backup
in the plant, one line per date with its count, and a reminder to stage
by explicit path, never withgit add -Aorgit add .. - When the plant is its own Git repository and ignores
.cypress/seed.json,
the installer prints the.gitignorelines that keep the stamp and the
coverage record tracked. It never edits.gitignore. - A stamp key an earlier seed wrote and this one no longer reads is named
and kept. --kernel-mode composekeeps a team's ownAGENTS.mdcanonical: the
installer never writes it, andCLAUDE.mdimports it on its first line
and carries the kernel after it. The cost, stated on every run: a host
that reads onlyAGENTS.md(opencode, Prime Agent, Codex, Copilot) never
sees the kernel. The mode is recorded in the stamp askernel_mode;
--kernel-mode replace, the default, returns to one shared kernel body.
The installer refuses compose before writing whenAGENTS.mdis missing,
a symbolic link, or a body the seed wrote.graft-audit.pyreads a
compose-mode plant.- A crashed router is one line in the session,
No route: graph-lint.py exit <status>: <its last stderr line>, and the prompt still goes through
(SPEC-0003). --expertise skill-corpus/<name>places a generic skill page as the
routable nodedocs/graph/skills/<name>.md. Every skill-corpus page now
carries node frontmatter, and the installer refuses a page without it by
name.- A placed corpus page needs no row in the plant's
index.md: the plant's
graph-lint.pyreadsorigin: corpus@<version>as an entry point
(SPEC-0001 PLACED_CORPUS_PAGE_IS_REACHABLE). - The matcher proposes the Microsoft Graph platform page for the Graph SDK
packages.
Graft, grow and harvest
- Graft makes the baseline commit itself before its first write, per the
plant's version-control shape: one commit of the tree as found in the
plant's own repository, staged by explicit path, or a.gitignoreand
git initwhere the plant has no repository of its own. It commits a
checkpoint after a ratified flag flip, after the apply, after each remedy
that re-runs the installer and at the end, and records each commit.
Nested repositories stay read-only. It never fetches, switches or pushes. - Graft lists the backups by date for the owner's decision on which to
keep, offers compose mode to a plant that keeps its own hub, and records
the owner's own words for a plant fact beside the value. - Graft and grow read what the plant needs (its recurring procedures, the
tools and services it drives) as well as what its manifests name, and
propose the corpus page that serves each need with the path that shows
it. graft.gate.routesrecords a plant's own adversarial routing baseline
withagent-lint.py --eval --record-baselineat the graft that brings
the routing corpus or changes the roster, and gates the plant on it. The
seed's roster keeps its budget.- Grow commits a baseline before its first write and a checkpoint at the
close of every phase that wrote, andgrow.gate.write-scopereads each
phase against the commit that opened it. A corrections record takes what
authors find after the evidence ledgers freeze, and outranks them. An
owner-stated fact no file witnesses is recorded once, labelled, with the
owner's words. - Harvest's check that a plant was left untouched compares content hashes
of dirty, untracked and read ignored files, so a write to a file that was
already dirty is caught. A harvest that re-reads a plant it already read
takes a fast path, and its agnosticism check takes--forbid-file.
Doctrine
- Two new delegation leaves:
delegation-wave-integrity.md(each worker's
write set in a table, a wave baseline, output that survives an
interrupted spawn) anddelegation-continuation.md(when to resume an
agent that already handed back, and when to brief a fresh one). - Every worker runs its own route. Architect, product, devil's advocate,
UI/UX designer and legal gain Bash, which their charters limit to lookup
and measurement; legal's shell never reaches the network. A worker brief
no longer carries a closure the caller routed. - The graph-session bootstrap gains two steps: check the route against the
files about to be touched, and leave shared git state alone. - In an operations or verification pass, the tester lists each bug it
finds, root-caused, and the fix waits for the owner's go-ahead. Outside
such a pass the default stands. - A project's own authorization levels and the seed's tiers are two axes;
the stricter wins, and neither is translated into the other. - Decision points offer numbered options with a recommendation. A spec's
failing tests are planned as one wave, with mutation testing batched at
the end. - The release, secrets, contract, host-parity, version-control, design,
incident and stewardship postures take the rollback, backup, credential,
contract, reconcile and diagnosis rules plants had written for
themselves. skill.library-wikinow holds the rule for which dependencies get a
full page when adopting a project, and files a staged research-scout
draft at close-out. The templates gain setup sharing in a spec's §10,
rollback per unit, and a record of declined tool candidates.
Corpora
- Library corpus: 27 new pages and 16 rewritten whole; seed claims the
review found wrong were corrected against upstream sources. A page for a
library in preview, or whose next major is a release candidate, says so. - Tool corpus: 11 new pages and 9 integrated. The seed-data page says a
demo password lives on disk only, in a file no model reads. - Skill corpus: new generic and stack-keyed pages.
discardmeis now
change-review-report: the report a reviewer accepts or rejects a
substantial change from without reading the diff. - Legal corpus: one new EU regulation page, and four more GDPR provisions
from the publisher's current text.
Tools and checks
source-index.pyanswersincompletewith a named record where it used
to give an empty answer or refuse:language-not-readfor an input in a
language it does not read,reached-over-httpfor a test that reaches
the code only through a URL, andrepository-unnamedfor a work tree
nested in the plant, while the rest of the moved list is answered.session-metrics.py --allnames on stderr why it found no entry.spec-lint.pyreports a contract slug that only a comment carries as a
WARN, never as coverage, under a ratchet that may only fall
(--comment-only-budget).graft-audit.py --recordreads any heading that names a graft, in any
case or position. An entry whose lists name no file fails; a graft that
merged and kept nothing writes- none.agnosticism-lint.pytakes--forbid-file(with!allowlines),
--optional-forbid-file,--trackedand--terms-only. A new gate step
lints every tracked file against the steward's local, gitignored
.cypress/forbid.txt, and prints SKIPPED where that file is absent.- The gate has 52 steps (
python3 tools/gate-registry.py --summary).
Upgrade notes
- Install Python 3.14 first. The installer finds
python3.14and writes
it into every hook; with no Python at 3.14 or newer onPATHit refuses
before writing. Put apython3at 3.14 first onPATHfor agent
sessions as well. - Graft commits. The next graft makes a baseline commit of the plant's
own repository before it writes, then checkpoint commits. It names each
untracked path and stages none you have not admitted. - Keep the stamp tracked. If the installer prints
.gitignorelines for
.cypress/, put them in place of a rule that ignores the directory. - Decide on backups. The BACKUPS block and graft list them by date;
which to keep is your call. - Plant agents gain Bash. A plant-authored agent without a shell is
given one at the next graft, in a proposal you ratify. - Record the routing baseline. A plant with its own specialists records
its adversarial baseline at the next graft. - Spec coverage may drop. A plant test that names a contract only in a
comment no longer covers it; name the contract in the test's code. - Steward checkout. The gate reads the local
.cypress/forbid.txt; a
release waits for that step to read PASS in the checkout that holds it. - New rules in the protocols, method nodes, agents and templates reach an
existing plant through graft.
Identifying toke...
v8.1.2
8.1.2 — a plant is ready to go from the get-go (2026-10-09)
After an install, a graft or a grow, the source index is already built, and
the owner reads in one short report what is set up and what still needs a
fix. Nothing is left to do by hand that the report does not name. A session
finds the tool through a seed skill, the kernel names it, and a question
about a file the plant owns loads that skill beside the node that owns the
file.
The build report
install.shrunspython3 docs/graph/source-index.py buildas its last
step, on every install that places files and so on every graft, and prints
the report undersource index build (advice, never a failure of the install; ...). The build runs in isolated mode (-I -B) with stdin
closed and a 120-second bound. An install never fails on it: when the
build does not finish, one line says so and gives the command to run by
hand.tools/growth-audit.pyprints the same report after its verdicts, at
every grow and graft. It is advice, never a verdict, and never sets the
exit code;--jsonappends it as{"source_index_report": [...]}.
graft-run.pykeeps both copies, ininstall.logandcoverage.txt.- The report holds the cache line, the counts and the build time, then one
record per setup gap, each with afix:line under it: arepo:value
that names nothing on disk (repo-unresolved), a Git repository inside
the plant that no node names (repository-unnamed, new), a missing or
empty test declaration (no-test-declaration,no-test-files), and the
rest. Hints name files that look like tests but sit outsideTEST_GLOBS,
files in the test class that do not look like tests, and patterns in
docs/graph/source-index.jsonthat match no file
(config-pattern-unmatched, with its own fix line). - The cache bound,
CACHE_MAX_BYTES, rises from 64 MiB to 196 MiB.
Finding the tool
- A new seed skill,
skill.source-index(skills/source-index/SKILL.md),
is placed and projected like every seed skill. It sends the four
questions (what depends on a file, which tests a change reaches, which
pages cite a file, where a name is defined) to the tool, says how to act
on the build report, and states the limit: an answer is a recommendation,
and a file missing from it is never proof that the file is unaffected
(ADR-0030).
The seed now ships 16 skills; the Codex config example registers the new
one, and the always-loaded surface on Claude Code grows to 25 800 bytes. - The kernel's "Where to look next" gains one line for code questions:
python3 docs/graph/source-index.py --helpandskill.source-index.
The owner raisedKERNEL_BUDGETfrom 8 000 to 8 200 bytes for it. - verify, canonize, grow and graft list the skill as a peer.
The router
- When a task names a file that a plant node owns and also holds a trigger
phrase of a seed skill, the router loads that skill beside the owning
node, at most two skills (PATH_TIER_SKILL_CAP); a task that holds the
phrases of more loads the node alone. Only skills the seed ships are
added this way (SPEC-0002, ADR-0026 "Amendment, 8.1.2"). - A file path or a code name inside a trigger phrase no longer breaks it.
A path stands in for the phrase's wordfileand a code name
(save_order,saveOrder) forname, so "what breaks if I change
src/app.py" holdswhat breaks if I change this file. An ordinary word
still breaks a phrase.
Graft and build output
- A graft now names an outdated seed page left in a plant (a file under
protocols/ormethod/that the seed no longer ships, such as
protocols/toolcraft.md) as RETIRED, and ties the graph-lint errors it
causes to that page. It deletes nothing: the steward removes the page by
name (migration (d)). A test graft on a copy of wrt-migration found the
case. - The build report's
Incomplete:line stops at the row limit and ends
withand N more;--alland--jsonshow every row. - Memory was measured near the 196 MiB cache bound: about 100,000 files,
where a query needs about 1.3 GB.
CI on macOS
tests/test-source-index.shchecks howrepo:values with different
letter case are read only on a file system where case matters. It probes
first and, on the macOS runner's case-insensitive disk, skips those two
checks with a printed reason instead of failing.
v8.1.1
8.1.1 — the gate checkout fetches full history (2026-10-07)
The CI gate cloned the seed without history or tags, so two tests that
read the v7.36.0 engine failed on GitHub since 7.37.0. The gate now
fetches the full history, and seed-lint requires it.
Gate checkout
.github/workflows/gate.ymlfetches full history (fetch-depth: 0) on
checkout, so gate tests can read git history and tags, such as
git show v7.36.0:....tests/seed-lint.pyrequires the full-history checkout, with
tests/test-seed-lint.shas its RED/GREEN test.
v8.1.0
8.1.0 — the source index: what a change reaches, read from the code (2026-10-07)
A plant can now ask which code depends on a set of files, which tests a
change reaches, which graph pages cite a file, and where a name is defined,
and get the answer from the code without a model. The tool is
docs/graph/source-index.py. Verify, canonize, grow and adopt-existing each
call it once, at the step that needs it. It recommends; verify and tiering
still decide what runs and how much process a change gets.
A node's repo: value now decides what it claims on disk, the same way
everywhere the graph reads it. A folder or a file, named with or without a
trailing slash, claims the paths under it; a repository or the plant root
claims nothing. A plant that holds a repo: value naming a folder or file
without a slash, such as src/ or a bare folder name, starts routing on
it after its next graft. A value that names nothing on disk is read as
before, and anchors now says so with a repo-unresolved note asking the
owner to correct it. The node template's comment states the rule: one
plant-relative path.
Source index
tools/source-index.pyis placed atdocs/graph/source-index.py. One
reverse walk over file-to-file links answers three queries:impact, the
code that depends on the inputs, nearest first;affected-tests, the same
walk filtered to the plant's tests, plus an always-run set; andanchors,
the graph pages that cite the inputs, with knowledge nodes kept apart from
plans, specs and decisions.buildforces a rebuild.symbols <name>lists every definition of a name, with path, line and
kind, and never picks one when several files define it. A Python
definition, read withast, iscertain. A shell function, or a
TypeScript/JavaScript declaration at the top level of its file or
exported, is read line by line and ismaybe. A file the tool could not
read makes the answerincomplete, with the action "search by hand".--historyadds toimpactandaffected-teststhe files that changed
together with an input in past commits. Each is amayberow in a
historylist of its own, with the number of commits the two files
shared out of those that changed the input. History only adds rows. A
shallow clone, or a repository with no history, makes the answer
incomplete.anchors --movedtakes its inputs from the moved list of
code-anchor.py, the files changed since the anchor was recorded, so no
paths are copied by hand. With no anchor, the answer isincomplete.- Links come from Python imports, read with
astand never run;python3,
bash,shandsourceinvocations; quoted path literals, whole or
joined from segments; and TypeScript/JavaScriptimport,export from,
require()andimport(), resolved throughtsconfigpathsand
baseUrl. A mention in Markdown is not a link. - Each row is
certainormaybe, and amayberow names the reason and
line of its weakest link. A file whose references cannot be pinned, such
as a whole-tree walk or a dynamic import, givesmayberows that every
input reaches alike. These are the floor, listed once after the input's
own rows. What the tool cannot answer makes the answerincomplete, with
a reason and one action: check by hand, run the full suite, or review by
hand.affected-testsnever presents its list as the only tests to run. - The tests are the plant's
TEST_GLOBSindocs/graph/spec-lint.py. A
plant can setexclude,always_runandglobal_inputsin
docs/graph/source-index.json, which is its own file; the installer never
places it. - The index is derived scratch in
.cypress/source-index/, beside an inner
.gitignoreof*. Any query rebuilds it when its key changes (a commit,
an uncommitted code edit, a config edit, a graft that changes the tool,
another Python version), and deleting it is safe. A graft rebuilds it and
never carries it over.
ADR-0029
records the decision; the owner accepted it on 2026-10-07.
SPEC-0007 holds the contracts. - The tool needs the Python standard library and
git, nothing else.
The protocols call it on demand
Each step below runs the tool once. No hook runs it, and nothing runs it
per prompt or per file access, the pattern ADR-0018 withdrew.
verify: after GREEN and before the gates are chosen,affected-tests
is the recommended floor of the focused tests. The session may run more,
and never reads a test's absence from the list as proof that the change
cannot reach it. Anincompleteanswer puts the change in the "affected
scope genuinely uncertain" row.canonize: in flow step 1, beforecode-anchor.py --record, the session
runsanchors --movedand hands the pages it names to the docs-librarian
to re-check. Recording the anchor first would empty the list.growandadopt-existing: before the scouts are briefed, the
inventoryfrombuild --jsonis their file list. On a refresh,
impactover the moved paths gives the blast radius.
One home for the path rules
tools/source_paths.py, placed atdocs/graph/source_paths.py, holds the
rules for what counts as code, which repositories a plant governs, where
Git ends, the content hash, the atomic write under.cypress/, and how a
page cites a path.code-anchor.pyandgrowth-audit.pynow use it; their
behaviour is unchanged, and their existing tests prove it.tools/plant_walk.py, the walk over one plant's files thatgraft-audit.py
already used, is now also placed, atdocs/graph/plant_walk.py, because
source-index.pyloads it.
Measured
The figures come from copies of each tree, at seed commit 17d4539, before
the tool read paths joined from segments; nothing was written into a real
plant.
- On a temporary plant over a clone of the seed,
affected-testsanswered
for 48 past commits that changed at most three source files, scored
against the tests each commit edited, out of a set of 40. The full answer
(tests, always-run and floor) found 0.989 of them, but named 38.0 of the
40 tests on average: on the seed it suggests nearly the whole suite. The
input rows alone (tests and always-run, no floor) found 0.880 at 21.7
tests, and they are the useful part on the seed. Thecertainrows alone
found 0.120, because most of the seed's links are path literals, which are
maybe. - A full build of the seed plant takes 0.67 to 0.76 s, and a cached query
0.10 s. A TypeScript plant of 397 files builds in 0.66 s, and a llama.cpp
clone of 4,320 files in 3.19 s.
Checks
- The gate has 51 steps (
python3 tools/gate-registry.py --summary). tests/test-source-index.shholds the source index, on synthetic Git
plants.
Upgrade notes
- New placed tools. Every install now places
docs/graph/source-index.py,docs/graph/source_paths.pyand
docs/graph/plant_walk.py, fast-forwarded like the other seed tools. The
installer writes no index; the first query builds it. - Set
excludebefore reading an answer as a gate set. A plant's
TEST_GLOBSoften match fixtures, helpers and a suite runner. List them
underexcludeindocs/graph/source-index.json.
Known limits
symbolssays where a name is defined, not who uses it. A TS/JS class
member, an indented declaration that is not exported, and a definition in
a shell here-document are not read.- History does not follow renames, and a CI checkout that holds one commit
gives no history rows, so every--historyanswer there is
incomplete. - Hook commands written in host settings files, such as
.claude/settings.json, are not read, so a hook script has no dependent
in any answer.
v8.0.0
8.0.0 — corpus pages placed on request, a deeper corpus, and sharper doctrine across the lifecycle (2026-10-05)
A plant can now ask the seed for the corpus pages that match its own stack,
one by one, and get version-aware library, skill and tool pages it can work
from without a research pass. The corpora are much larger. Planning,
delegation, the postures and the lifecycle protocols carry new rules. A
placed tool reads the session-metrics block of every full delivery. This
release is a major version because it adds a placed tool, a stamp key and
stricter checks that an existing plant meets on upgrade (see Upgrade notes).
Install and selective placement
install.sh <host> --expertise proposeprints the library, tool and
stack-keyed skill pages that the project's manifests match, one line per
page with the manifest entry that matched, and writes nothing.
tools/corpus-match.pydoes the matching; it runs from the seed and is
never placed.install.sh <host> --expertise <id>[,<id>...]places exactly the pages
named: library pages atdocs/graph/libraries/<name>.mdand tool pages at
docs/graph/tools/<name>.mdunder a provenance line, and a stack-keyed
skill page as the nodedocs/graph/skills/<name>.mdwith
origin: corpus@<seed version>. The list is recorded in.cypress/seed.json
underexpertise, with the SHA-256 of each page written.- Each later install refreshes the recorded pages nobody edited and names
each edited page for graft.--checknames a recorded page that is
missing or stale. growproposes the list,graftrefreshes it, andingest-libraryskips
the scout for a placed page and pins only the version delta
(ingest-library.corpus-first).
Seed defects fixed
- The graft ledger takes an honest lineage base and accepts
--base-dir.
graft-runinfers the adapters of an old stamp. graft re-checks at the end
every file its record says it merged or kept. status-migratekeeps multi-line statuses and invents no dates.
growth-auditdeclares grounding it could not check.- graph-lint's artifact escape check is lexical, so a symlink install no
longer reports false escapes. spec-lint and grill-lint refuse a misnamed
spec instead of passing over it. - A missing hook script prints one
cypress: hook script missingline
instead of nothing, andinstall.sh --checkruns each wired context hook
once. A harness agent or skill with no graph home is named RETIRED or
ORPHAN; nothing is deleted. - The hooks detect deeply nested input on any Python version. The installer
resolves the legal jurisdiction once per run. - Router triggers are sharper, and the adversarial ratchet is 2.
Corpora
- The library corpus grows from 91 to 131 pages, with new
galaxyandpub
ecosystems. Pages state the version facts the library's own docs document
(a minimum version, a version where behaviour changed) next to their
subject, and a section per major line where the surface differs. - The skill corpus grows from 12 to 33 pages. Stack-keyed pages live at
skill-corpus/<key>/<name>.md, carry node frontmatter and astack:field,
and can be placed as routable skill nodes. - The tool corpus grows from 24 to 40 pages, each with a self-test where the
page claims portability. A tool page may carry the samestack:field. - The agent corpus grows from 6 to 8 roles, including discipline roles on a
stack-shaped surface. - The legal corpus grows from 13 to 16 instrument pages: PSD2, the SCA
technical standards and EDPB Guidelines 2/2023, plus two more provisions of
the national data-protection code. - Every corpus admits a page only at the withdraw-ready bar: a new plant
could adopt it instead of running a research scout. Pitfalls, steps and
rules from problems met in practice are written into the pages that own
their subject.
Doctrine
- Planning: a scoped standing grant for repeated non-production acts, asked
for once at plan approval (vcs-posture.publish-authorization); a walking
skeleton first for a new pipeline or deploy path, with a spec that grows one
signed slice ahead of each RED; an environment-parity read for a plan that
changes a deploy chain; an operational act that closes on evidence of the
act, not of the tool that performs it. - Delegation: an error signature is not a failure class; a provisional
reading inside a contract keeps a worker going until the ruling pass; the
run that gates the goal goes first; work split by area is routed area by
area; a worker that hits a limit is resumed, not respawned. - Postures: a control sits where the party it must stop cannot edit it; leak
triage settles liveness by digest and verifies a rotation at the consumer;
records a system already holds start unmanaged; a green dry run is
structural evidence only, and a target selector is resolved to hosts before
a mutating run; staging-only machinery refuses a production profile; a
changed producer field updates its consumers in the same change. - Lifecycle: grow treats an agent-operations system in the source as
evidence; canonize keeps a harvest-candidate record from
docs/graph/plans/_harvest-candidates.template.mdand asks for missing tool
and library pages at close-out; deliver requires the Session metrics block
on the full form and records a production fault in the incident runbook; a
ratified ADR takes an appended, dated Correction. - The harvest protocol now takes knowledge whole. It generalizes a
candidate instead of rejecting it, admits a stack-bound procedure as a
stack-keyed page, and admits the version facts a library documents. It
never states a plant's own version, and it leaves security warnings and
CVE ids to scanners. Each fact carries a provenance class, candidates read
from more than one project are consolidated first, a lesson goes into the surface that
already owns its subject, and an independent reviewer reads each lane.
ADR-0028
records the decision.
Session metrics
tools/session-metrics.pyis placed atdocs/graph/session-metrics.py.
deliver runs its lint role on the full-form entry it appends to
changelog.md, and harvest reads its query role. It takes the block's
labels from the plant's deliver node at run time.
SPEC-0006 holds its contracts.
Checks
- The gate has 50 steps (
python3 tools/gate-registry.py --summary). tests/test_corpus_match.pyholds the matcher, and
tests/test-session-metrics.shthe session-metrics reader.tests/test-tool-corpus.shruns the self-test of every portable tool page
and a mutated copy.- The two knowledge-graph templates are held by prose-lint.
- SPEC-0001 carries the selective-placement, hook-check and
harvest-candidate form contracts, and SPEC-0003 the missing-script
warning.
Upgrade notes
- New placed tool. Every install now places
docs/graph/session-metrics.py, fast-forwarded like the other seed tools.
A full-form delivery whose Session metrics block is missing or malformed
is reported by it. - Nothing is placed from the corpora by default. A plant gets library,
tool or skill pages only through--expertise. Once it has used the flag,
.cypress/seed.jsoncarries anexpertisekey, and later installs refresh
the recorded pages it has not edited. - New blank form in
plans/. The docs scaffold adds
docs/graph/plans/_harvest-candidates.template.mdwhere it is missing;
graft treats it as expected. - Stricter spec discovery. After graft reconciles the graph engines, a
Markdown file indocs/graph/specs/that is not namedSPEC-*.md(index
and readme aside) fails spec-lint and grill-lint as a misnamed spec. Rename
it, or it is never checked. - Louder hooks. A context hook whose script is missing now prints one
line naming it.install.sh --checkruns each wired hook once, names each
recorded expertise page that is missing or stale, and names harness agents
and skills with no graph home. - New rules in the protocols and method nodes, as listed above, reach an
existing plant throughgraft. A new plant gets them frominstall.sh.
Known limits
- The
cli/library pages keep their documented minimum-version markers. - The portability gate breaks one property per page with a single mutation;
a self-test that misses other properties still passes it. skills/adopt-existing/SKILL.mdsits at the 170-line leaf ceiling. Whether
it moves to the lifecycle class or the ceiling is raised is the owner's
decision.- ADR-0028 is proposed and waits for the owner.
v7.37.1
7.37.1 — two decisions of 7.37.0 ratified by the owner (2026-10-01)
Changed
- ADR-0026 (the node router's tier ladder and its gated corpus) and ADR-0027 (the first move runs the router) gain a Ratification section. The owner ratified both after the 7.37.0 release. No code, check or node changed.
v7.37.0
7.37.0 — the first move runs the router, and a session pays for a route once (2026-10-01)
The owner asked for fewer model-facing tokens, not for speed. One --plan
run already takes about 70 ms, so latency was never the cost. The cost was
text: Prime Agent injected the full route on every prompt, a route printed
the same facts several ways, and every session opened docs/graph/index.md
before it knew what the task needed. This release cuts that text where a
program can derive it, and keeps every pointer a model follows.
What a plant gets
- The FIRST MOVE routes the task line. A session takes the router
suggestion the host injected, or runs
python3 docs/graph/graph-lint.py --plan "<task>", reads the LOAD nodes
throughgraph-lint.py --show <id>..., and acts on any!notice.
docs/graph/index.mdbecomes the fallback map: a session opens it when the
router fails, when a notice leaves the plan empty or wrong, or when the task
explores the graph itself. The orchestrator's Turn 0, the
knowledge-graphtier table,_schema.mdand the docs map say the same. - Prime Agent keeps one route per session.
install.sh prime-agentnow
places the sameroute-hook.pyandstatus-hook.pythat Claude Code runs,
byte for byte, under.prime/agent/hooks/. The two extensions pass the
prompt, the session id and the session depth to that core and compose no
text of their own. A node this session was already shown is named by id on
oneseen:line instead of being injected again. The status register and
the code-anchor line arrive once after each session start, compaction,
tree switch or refine. The overlay's## Surfaced nodessection, a set the
model kept by hand, is gone. - Children and non-human turns are not routed. A spawned child session
(depth above 0) and a turn a person did not type (an agent message, a
task notification, a harness digest) get no route and no status text, on
every host that runs the core. - Route lines are compact and keep every path.
--planprints one line
per node with its file beside its id, a skip block, and the owner's
plant:facts when all four are filled. Programs read--plan-json, one
cypress.plan/1document bound to the prompt by its SHA-256. The hooks
read only that document and render the same lines from it. --showreads a node without its router keys. It prints a header with
every edge and leaf pointer resolved (requires,peers,composes,
delegates_to,artifacts,libraries,plant_knowledge), then the body
verbatim. It drops only router input, spawn settings and copies of the body.- The node router abstains instead of guessing. It takes the first tier
that hits: an exact node id in the task, a path the task names, a trigger
phrase of two or more content words, then the word score with a floor of
two confident terms. A strong tier that hits more than three nodes falls
through. A task with no signal, or one too long to be a task line, loads
nothing and gets a short notice that names the next step. Root is no longer
forced into every plan.
Measured
Model-facing tokens are cl100k counts from the round's records; each run
replays real sessions from the steward plant against the uncommitted tree.
- Follow-up prompts: 47 follow-ups across 22 real sessions fell from 36,402
to 11,131 injected tokens (-69%). - Five real prompts in one session: 5,885 to 2,306 tokens (-61%).
- First-move window of short sessions: Prime Agent 25,359 to 14,739 tokens
(-42%, 15 sessions), Claude Code 56,189 to 32,418 (-42%, 9 sessions). This
assumes a session no longer readsindex.mdfirst. On Prime Agent the
saving holds while fewer than about 14% of short sessions still read it;
before the change, 5 of 15 did. --showover the plant's 116 nodes saves about 216 tokens per opened node
and keeps 651 of 651 pointers.- Routing quality on a 74-row plant corpus: adversarial rows hit a forbidden
node 2 times, down from 19, and 8 of 9 unknown-domain tasks now abstain,
up from 1.
Known limits
- A plain re-install keeps a plant's older
graph-lint.py
(ADR-0014). The
new hook then injects one line saying the engine lacks--plan-json, until
graftbrings the engine up. - The FIRST MOVE now needs
python3. A shell-less GitHub Copilot mode can
only take theindex.mdfallback; Copilot is a frozen host and gets no
adapter work. - The hook waits up to 15 s for the router before it gives up and injects
the pointer line alone.
Decisions and checks
- ADR-0024:
one Python hook core and per-session residency on Prime Agent; children and
non-human turns are not routed. It supersedes ADR-0010 in part. - ADR-0025:
compact route lines with every path,--plan-jsonbetween programs,
--showfor reading nodes. - ADR-0026:
the tier ladder, the abstentions, andgraph-lint.py --evalover
tests/graph-routes.golden.tsv, gated per class on theGRAPH_*ratchets
bytests/graph-route-eval.shintests/run.sh. - ADR-0027: the
FIRST MOVE runs the router andindex.mdis the fallback map. It amends a
consequence of ADR-0017 in part. - SPEC-0001, SPEC-0002, SPEC-0003 and SPEC-0005 carry the new contracts.
tests/test_graph_lint.py,tests/test-prompt-hooks.sh,
tests/test-full-install.shandtests/test-install-placement.shhold
them.tools/code-anchor.pyno longer counts__pycache__/,*.pycor
installer backup files as code.
How plants pick this up
- A new plant gets all of it from
install.sh. - An existing plant needs
graft: it brings the engine, the kernel's
FIRST MOVE and, on Prime Agent, the hook core under.prime/agent/hooks/.
A plant that re-installs an adapter withoutgraftgets the one-line
engine notice above in place of a route.
v7.36.0
7.36.0 — a declarative edit is proved by a run, not a new test (2026-09-30)
An owner reported that a plant, asked to add a selector to a pipeline, set
out to write a RED test first. That test could only read back the line it was
testing: red while the line is missing, green once it is there. It proves
nothing the diff does not already show, and it breaks on the next rename.
The rules led the worker there because they said, with no qualifier, that
every production change starts from a failing test. This release adds the
missing qualifier and puts the question where increments are planned.
What a plant gets
- A change with nothing to get wrong earns no new test. Before RED, the
worker names what a test could catch that the edit being present does not
already guarantee. For a declarative edit (a selector, a pipeline stage, a
route, a flag, a config key, a mapping entry, a label) the answer is
usually nothing. The proof is then the run that shows the edit working: an
existing test or gate over that surface, or the cheapest real run (a
dry-run, a validate command, one pipeline run), named with its result in
the handback. A declaration that holds logic still earns a test: a pattern
(regex, glob, wildcard), a condition, an order that changes the output, or
a computed value. The rule lives intest-first.proportionate-checks. - The planner asks first.
grill.increment-shapeasks of every
increment whether it needs a test. A no reads
Tests to write (RED): none — <why>; proved by <run>, and that increment
gets no RED spawn: the implementer makes the change and runs the named
proof, and review and commit stand. When the planner cannot tell, the row
keeps its test and the tester decides at RED, handing back unwritten if
the answer is no. The grill template shows the form. - Spec coverage counts the run.
spec-lint.pytreats the live contracts
that such a row names as covered by its run, and says so in its PASS line
and in--list. A row that readsnone — consolidationcovers nothing. - The tier does not move. A config or selector edit still changes
behavior, so it is T2 or above and keeps its reviewer audit. On the
contained lane the recorded run takes the place of the pinning test, and
the why-record names "test or run".
What changed and why
- The kernel's §3.4 anchor gains one line pointing at the exception, and
method.tiers' contained lane, the test-first rule statement and the
canonize why-record point attest-first.proportionate-checksinstead of
contradicting it. - The test-first exceptions list replaces "Pure configuration changes" with
"Declarative edits with nothing to get wrong". The old entry applied only
where there was no unit-testable behavior, and almost any edit is
unit-testable in the weak sense, so it never stopped the read-back test. - The implementer's contained-lane handback and the tester's step 3 name the
run as the proof for such an edit.
Decisions and checks
- ADR-0023,
proposed, amends ADR-0006 in part: the contained lane still trades the
spec for proof plus a why-record, and the proof is now the one the change
earns. Its named risk is a worker calling logic "declarative" to skip a
test; the logic list above is the check, and the reviewer audits the
claim. tests/test-spec-lint.shcase P1 holds the run-proved coverage and the
consolidation case.
How plants pick this up
- A new plant gets the rule from
install.sh. - An existing plant gets it by
graft. Plans written before it keep
their test rows and stay valid; thenone — <why>; proved by <run>form is
available to new increments. A plant that already recorded a declarative
edit under the old "Pure configuration" exception needs no change.
v7.35.0
7.35.0 — positive voice: rules say what to do, plants name their models once (2026-09-30)
The owner asked for a seed-wide re-reading of every prompt, to turn "don't do
this" into "do it this way, because", to clear accumulated cruft, and to fix
whatever had gone stale on the way. This release is that pass, plus the tools
that four of the owner's rulings needed.
What a plant gets
- Rules in positive voice. Every protocol, skill, agent charter, method
node and template, and the agent- and skill-corpus pages, state the
behavior they want and the reason for it. A bounded role says what it ONLY
does. A prohibition stays only on a hard boundary (an irreversible act, a
security, privacy or legal line, a user-sovereign trigger, loop control)
and names the right move beside it.
The rule's home ismethod.engineering-posture§8. Meaning is unchanged
except where a statement was false against the code; the main corrections
are listed under "Corrected facts" below. - A model map. A plant names its models once, in
docs/graph/models.md:
the providers, and the model each host runs for each class and effort.
Nodes, protocols and briefs name only the class (authoring or
investigation) and the effort. On Prime Agent the overlay reads the map,
resolves the selector withrlm.find_models, and spawns with
rlm.spawn(..., model=..., thinking=<effort>); a selector that does not
resolve stops the spawn, and an unfilled row inherits the parent's model
and says so in the routing evidence. On opencode,install.sh opencode
writes each agent'smodel:line from the map, and
install.sh opencode --checkreports drift. Claude Code reads the class
alias itself, so the map has no Claude Code column. The Prime Agent
overlay's version table and its "nearest higher model" fallback are gone.
agent-lint.py --lintrule 6 holds an agent'smodel:to the four aliases
Claude Code reads:opus,sonnet,haikuandinherit
(ADR-0022, which
supersedes ADR-0019 in part). - One companion block in every brief. The spawn id, the routing evidence
and the handback requirement now travel as a second canonical block,
COMPANION, beside GRAPH DISCIPLINE in
templates/prompts/graph-session-bootstrap.md. Seed-lint holds every copy
of both blocks byte-identical. - Known bugs. A bug a test uncovered is marked for a fix and the owner is
told. The test that found it stays unchanged as the bug's only acceptance
check; the implementer fixes the bug and the same test is re-run, and until
then the red is declared in the delivery (test-first.known-bug). - Retractions. A recorded claim found false is struck through, with a
dated Correction beside it.skill.holistic-editingis the one home of
that rule, and graft uses it for a plant fact it corrects. - The humanizer scope. The humanizer pass applies to prose a person reads
(documentation, extensive comments, handoffs and briefs for people,
ADR and spec bodies). Graph nodes and session records get none, because
the graph is written for models;prose-lint.pystays the floor. - Corrected facts, among others: the orchestrator's cold-repo route goes
throughprotocol.initialize; the legal referrers name the base-roster
agents/14-legal.md, andagent-corpus/legal.md, a duplicate of its
mandate, is removed at the owner's go-ahead; SSH
hardening allows root login by public key and refuses it by password
(PermitRootLogin prohibit-password); the
deploy-fleet-on-remote-docker-hostskill-corpus page uses
StrictHostKeyChecking=accept-newwith a committedknown_hosts; the
skill-corpus release page defines its "release branch".
What was removed
- The closing prohibition lists ("What you do not do", "Anti-patterns",
"Common ways to fail", "Forbidden moves", "What stays out of scope"), after
each rule they carried moved into the section that owns it. The fact key
holistic-editing.forbidden-movesstays; its section is now "Integration
moves".skill-corpus/discardme.mdis unchanged this round, and the
Anti-patternscatalogs oftemplates/knowledge-graph/_schema.mdand
multi-agent-architectstay, because they are catalogs, not closing
lists. - The
KNOWN_BUG_<id>assertion marker inprotocol.verify-disagreementand
every copy of it. - History narration in doctrine ("until 7.x", "added in", "was split"). A
sentence that carried a rule's reason now states the reason in the present
tense; the history stays here, in the changelog.
The owner's rulings
The round asked the owner ten questions. The answers: the reference pages
keep their walkthroughs and stay current (D1); lint holds the brief
companion aligned (D2); the humanizer's LICENSE.upstream names the
doctrine's holder (D3); SSH host keys and root login as above (D4, D5); the
skill-corpus "unsecured lane" is defined as a release branch (D6); known bugs
as above (D7); retractions as above (D8); one model policy for Prime Agent,
Claude Code and opencode, where Prime Agent and opencode may run any
provider (D9); and templates/knowledge-graph/_schema.md keeps its
frontmatter house style with two named exceptions (D10).
New checks
check_seed_only_stays_home:docs/skills/seed-release.mdand
tools/prepare-release.pyare never named bymanifest.jsonor
install.sh, and the manifest'stoolsmap equals whatinstall.sh
places.check_decision_index:docs/decisions/index.mdlists every ADR file, and
every link resolves.check_reference_tablescompares each protocol'sload_whenstrings in the
protocols reference with its frontmatter, andcheck_published_counts
checks "N protocols" as it checks agents and skills.agent-lint.py --lintrule 6, above.tools/prepare-release.pyrefuses a CHANGELOG entry holding a##
heading that is not a version heading, because the entry would end there.graft-audit.py --unfilledandgrowth-audit.pyreport an unfilled model
map as a disclosed line, not a failure.
Decisions and specs
- ADR-0021: a
procedure that runs only on the seed's own tree lives underdocs/skills/,
and seed-lint proves it never reaches a plant. Its first procedure is
docs/skills/seed-release.md, the end-of-round release: one documentation
pass, the gate, the staged notes, the commit, the steward plant's canonize,
and the tag push on the owner's go-ahead.CLAUDE.md's Release section is
now a pointer to it. - ADR-0022: the model map,
above. Both ADRs areproposed. - SPEC-0001 gains the model-map contracts: the template is placed once and
then left to the plant, the opencode projection takes itsmodel:line from
the map or drops it, an unreadable map fails closed,--checkdetects
opencode drift, and the seed-only files are never placed. - SPEC-0003's brief-template contract covers the COMPANION block.
- SPEC-0005 (version 0.15) adds
AGENT_DECLARES_MODEL_CLASS. - The round's plan of record is
docs/plans/grill-7.35.0-positive-voice.md.
How plants pick this up
- A new plant gets everything from
install.shand the install prompt.
The model map arrives as a template; growth asks the owner to fill it with
the other plant facts. - An existing plant gets it by
graft. The machinery fast-forwards, and
the model map is placed because it is missing. Until the owner fills it,
graft reports it as a disclosed line, not a blocker, and every agent runs
on its caller's model. On opencode, re-runinstall.sh opencodeafter
filling the map. A plant agent whosemodel:holds a full model id fails
rule 6 after the graft; the id belongs in the map, andhaikuor
inheritkeep passing. - Skill-corpus copies stay the plant's. A plant that instantiated
deploy-fleet-on-remote-docker-hostorharden-docker-hostfrom the skill
corpus keeps its own copy, and graft does not refresh it. Compare its SSH
line and itsPermitRootLoginsetting with the corpus page and bring them
in line. - Routing text moved in a few places, as stale-fact fixes: the
verify-disagreementdescription and one of itsload_whenlines, the
growdescription (its scouts and authors are now named by class,
investigation and authoring), and thespec-authordescription, which
now citesrule.spec. In several agent, protocol and skill descriptions,
an all-caps word is now in plain case. A plant that keeps its own route
golden set may see rows move after the graft. - Existing
KNOWN_BUG_<id>assertions in a plant's suites are the
plant's own tests, and graft leaves them in place. When one of those bugs is
next worked on, followtest-first.known-bug.
v7.34.0
7.34.0 — a harvest: tests sized by contract, and grill-lint reads a spec's status from its frontmatter (2026-09-30)
A grown plant was harvested back into the seed. What ships here is the
general part: no plant identity, no stack, and no counts from any project.
Signs that a check costs more than it is worth. test-first.proportionate-checks
names four more. A test that passes on either of two implementations asserts
nothing, so it asserts the one mechanism, and a contract that allows two shapes
goes back as a spec ambiguity. Where a behavioral assertion is possible, no
test checks that code calls a function, imports a module or takes a path: a
mock that only counts calls fails on a rename and passes on wrong behavior.
A long setup, a helper of its own, or a comment that points at the one line
that matters marks a test as over budget, and the answer is a smaller test or none. A
property of a factory, a table or a loop is one case over the collection,
never one per element. The Mocking-everything anti-pattern in test-first now
links to the mock and either-or rules instead of repeating them.
A plan names contracts, not test cases. In grill.increment-shape, the
Tests to write (RED): field names the contract slugs and a case cap no
larger than the number of contracts. The tester names the cases. A plan that
lists test names writes the suite twice, once in prose that nobody runs. The
grill template follows the new shape.
grill-lint reads a spec's status from its frontmatter first, as spec-lint
already did. The spec template's body line says "see frontmatter", so
grill-lint read every spec as live and asked the plan to cover the contracts
of a retired spec. It no longer does. A regression case holds the fix.
The owner ruled that the doctrine changes carry no tests of their own ("don't
write tests about when to not write tests"). The lints are their proof.
Rejected: a second home for anti-patterns the skill already owns, and the
plant's own measured evidence.
Harvest log
# Harvest — from a grown plant — 2026-09-30
Harvested: four rules on an over-budget test in the test-first skill;
a contract-and-cap shape for a plan's RED field, with the
template; a grill-lint fix with its regression case.
No plant identity.
Generalized: plant names, paths, stack and counts stripped.
Rejected: a second home for anti-patterns the skill already owns; the
plant's own measured evidence.
Decided: the owner ruled that the doctrine changes carry no tests of
their own; the lints are their proof.
Seed integrity gate (verdicts only)
- G1 agnosticism-floor: PASS
- G2 agnosticism-judgment: PASS
- G3 faithful-import: PASS after correction (two thinned passages restored; one skipped rule added by owner ruling)
- G4 availability: PASS
- G5 plant-untouched: PASS
- G6 self-consistency: PASS
- G7 clean-install: PASS
- G8 prose: PASS, genre exception recorded (the heading dash and the version arrow are the entry format)
- G9 minimum-sufficient: PASS
- G10 provenance: PASS
- G11 no-loosened-limit: PASS
- Version bump: 7.33.0 → 7.34.0