Skip to content

feat(install): deliver the rules, don't just install them - #26

Merged
indykish merged 2 commits into
mainfrom
feat/runtime-loaders
Aug 27, 2026
Merged

feat(install): deliver the rules, don't just install them#26
indykish merged 2 commits into
mainfrom
feat/runtime-loaders

Conversation

@indykish

Copy link
Copy Markdown
Contributor

AGENTS.orly.md was reachable only through a prose pointer an agent had to notice and follow. Nothing loaded it — no import, no symlink, no hook, no settings entry. The same gap held one file further up: Claude Code loads CLAUDE.md and nothing else, so a repository carrying only an AGENTS.md handed its agent no rules at all. This checkout was itself an example, which is how the gap surfaced.

The install now writes one loader per runtime that has a deterministic way into context, and leaves the runtimes that have none to the read-record gate.

CLAUDE.md ──@AGENTS.md──> AGENTS.md ──@AGENTS.orly.md──> AGENTS.orly.md
   ^                          ^                              ^
   Claude Code                Codex, Amp                     opencode reads both
   loads this only            auto-load this                 from opencode.json
Runtime Auto-loads What lands
Claude Code CLAUDE.md only a CLAUDE.md importing the host, where the repository has none
Codex, Amp AGENTS.md nothing new — the pointer block was already there, and now carries an import
opencode nothing both rule files in instructions

The bare @AGENTS.orly.md line in the pointer block is the load-bearing half. Backticked it is decoration, which is what the block shipped as before: an import inside a code span stays literal text.

Your files stay yours

The loaders are the repository's files, not orly's. They stay out of managed, are written only where nothing was written before, and are never rewritten:

  • a CLAUDE.md of your own is untouched, reported rather than edited
  • a CLAUDE.md symlinked at the host counts as delivery — editing through the link would land in AGENTS.md and import it into itself
  • opencode.json gains the two missing instructions entries and nothing else; one orly cannot parse is left byte for byte
  • a loader symlinked outside the repository is refused up front, like the pointer host

Session notes 1

Delivery logic moved to src/loaders.ts — the concern's own unit, taking install.ts from 452 lines to 393.

README.md carried the claim this change disproves ("Every agent runtime auto-loads AGENTS.md"); it now states what each runtime actually loads. Questions 26.8 and 26.9 lock the behaviour into the invariance suite. No core/ or packs/ edit, so the rendered ruleset is unchanged.

Review

make audit green, make install-evals 23/23 green, including "a second init writes nothing and leaves the tree byte-identical" — the loaders are idempotent through the packed tarball path.

One finding, found by the push gate rather than by me: the three-way Verdict union repeated its own string literals, which RULE UFS forbids. ufs.sh scans git ls-files, so the working tree could not see it and the commit could — fixed in 4a12271.

orly gate pr green on every criterion.

Make

$ bash audits/ufs.sh --all
OK:   audit-ufs: no violations across 38 file(s)

$ make install-evals
  PASS  a second init writes nothing and leaves the tree byte-identical
  PASS  packed tarball installs and renders with no dotfiles checkout
  23 passed / 0 failed

End-to-end probe, a Go repository with its own AGENTS.md:

$ bash bin/orly init
🟢 43 written, 0 already current (8 packs)
$ bash bin/orly init
🟢 0 written, 42 already current (8 packs)
$ bash bin/orly doctor
🟢 this repository's installed ruleset matches .oracle/orly.json

Ships as 0.9.0 — merging to main publishes it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DTMFyrbXJo3UrzQygaNtcn

indykish and others added 2 commits August 27, 2026 22:44
AGENTS.orly.md was reachable only through a prose pointer an agent had to
notice and follow. Nothing loaded it: no import, no symlink, no hook. The
same held one file up — Claude Code loads CLAUDE.md and nothing else, so a
repository with only an AGENTS.md handed its agent no rules at all. This
checkout was itself an example.

So the install now writes one loader per runtime that has a deterministic
way in: a bare `@AGENTS.orly.md` import inside the pointer block, a
CLAUDE.md importing the host where the repository has none, and both rule
files in opencode.json's `instructions`. Codex and Amp auto-load AGENTS.md
and reach orly's rules through the block already there.

The loaders are the repository's files, not orly's: absent from `managed`,
written only where nothing was written before, and never rewritten. A
CLAUDE.md symlinked at the host counts as delivery and is left alone —
editing through it would import AGENTS.md into itself.

Delivery logic moves to src/loaders.ts, which is the concern's own unit and
takes install.ts from 452 lines to 393.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DTMFyrbXJo3UrzQygaNtcn
The three-way Verdict union repeated its own strings at every return. The
push gate saw them the moment the file became tracked, which the working
tree could not — ufs.sh scans git ls-files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DTMFyrbXJo3UrzQygaNtcn
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.65217% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/loaders.ts 95.38% 6 Missing ⚠️

📢 Thoughts on this report? Let us know!

@indykish
indykish merged commit c51423f into main Aug 27, 2026
4 checks passed
@indykish
indykish deleted the feat/runtime-loaders branch August 27, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants