Skip to content

Rule 24: what is being built, and a feature list of what that needs - #192

Merged
OpenCnid merged 7 commits into
masterfrom
d/response-artifact-framing-7b23e1
Jul 25, 2026
Merged

Rule 24: what is being built, and a feature list of what that needs#192
OpenCnid merged 7 commits into
masterfrom
d/response-artifact-framing-7b23e1

Conversation

@OpenCnid

Copy link
Copy Markdown
Owner

The build converged on the nearest familiar shape — a retrieval system with a fact store bolted on — because the target was written in records a construction decision never had to open. This adds the target as a rule, a feature list of what it needs, and the audit that found the drift.

The occasion was my own error. Hours after ratifying the slice/frame layering, I wrote into config.py that "a corpus arrives in ~500 round trips per GB" — presenting a bound as the lever for bulk transfer, an operation this architecture does not have. DATA_MODEL §6 is titled "The bounded materialisation exception" and says so in its first paragraph.

Rule 24 — what is being built

AMBIENT.md gains rule 24: Trellis is an agentic knowledge-work system over a large context of domain-specific user information — a toolset the user works with, not a retrieval system with a fact store bolted on. Two sentences carry it and one act falsifies each:

  • A query produces a deliverable, not a reply. A schema that can only carry a string cannot carry a deliverable — so a terminal action requiring non-empty prose, an artifact envelope with one hardcoded text part, and an answer sink rendering a single value each make it false.
  • The worker queries the corpus; it never transports it.

The collaborator wrote the charter sentence; the falsifiable clauses are what make it a rule rather than a description.

It is numbered last and printed first, deliberately. Rule 20 already names this failure for measurement — reach for a comparison because it is closer to hand than a target. Rule 24 is the same ordering one level up, and burying a target where construction cannot see it is the error itself. Fitting it compressed this file's least-decisive prose rather than growing past the ceiling (rule 22): 8,070 / 8,192.

What four read-only sweeps found

docs/architecture/, the prompt surface, the REPL-sandbox records, and the runtime — plus a fourth arm whose only job was to disprove the diagnosis. That arm changed the conclusion.

The diagnosis holds where it matters. No model anywhere is told what it is building (grep -i artifact over src/rlm/ returns two docstrings about module packaging). The deliverable is a string by schema at every layer. ITERATION BUDGET instructs the worker to collapse turns, against the doctrine's "composed over several turns."

And it is much narrower than "rebuild." The successor worker layer already has the corpus locate, a bounded narrow window, text-free get_ast_blocks, byte metering in both directions, and an llm_query whose context slot is typed Handle so a string cannot fit — built, with no non-test caller, while production spawns the legacy path. Grounded authoring is the response artifact done correctly for one case: a run with zero retrieval affordance that writes a multi-file directory. So the doctrine is implemented one layer down and one layer over from where the model actually lives.

A defect found while assessing the turn budget. When a run exhausts its iterations, rlms re-prompts the model over the whole transcript and returns that as FINAL_ANSWER — bypassing the answer channel: no literal check, no cap, no telemetry, no protocol violation. More turns spent composing means more chance of landing on the guard-free path, so the iteration budget cannot be widened before this is closed.

The feature list

docs/product/FEATURE_LIST.md — eight capability groups, every row marked shipped, built, unreachable, partial, absent, or PLACEHOLDER. Written before security hardening on purpose: a hardening pass over an unspecified feature set yields a queue of follow-ups rather than a boundary.

Collaborator answers folded in: the artifact is a Trellis-side object with A2A as one rendering; an artifact carries standing — filed as a fact, a belief, or a doubt — so §3 and §6 are one subject and artifact provenance rides machinery that already exists.

One conflation named. STANDING_MODEL.md is ratified with a status line authorizing no build, and its §3 says what that covers: the reduction "removes shipped engine surface", so deleting disposition code needs its own authorization. The gate is on a removal. Surfacing doubts/beliefs/facts as REPL state spaces is an addition, already designed in DATA_MODEL §7 as three pre-allocated root handles, and no gate covers it. It was never scheduled, not never approved.

Corrections to records written earlier in this branch

  • answer.submit(H) does not exist. Three places cited it as the route for bulk content; submit takes an expression string and renders a value, with no handle argument. The doctrine's wholesale hand-off is unbuilt, not capped — and an unbuilt escape hatch reads exactly like a built one.
  • The corpus is not bounded by address space. A layering table asked what corpus size RLIMIT_AS permits, putting the corpus inside the namespace — the one place the handle model says it never is. RLIMIT_AS bounds the working set.
  • TEST_TIME_TRAINING §12.2 is withdrawn from the audit. I read a literature-applicability argument as a workload target. §12.2 argues LaCT's long-context results do transfer — a claim about research relevance. TTT is a mechanism for rule 24's second sentence, not a counterweight: the composed prompt sets the mode, the model self-plays over REPL data, and properly filtered programmatic slicing is the rewarded behaviour, scored by RLVCG. It targets a local open-weights model that does not exist yet.
  • charge_outbound fires only for the llm_query prompt, so the answer is not on the exfil ledger, and THREAT_MODEL already calls the 64 KiB cap output-shaping "not a confidentiality or escape control." The collapse lives in DATA_MODEL §6 alone.

Verification

  • pytest 1,042; vitest 1,416 / 119 files.
  • check:repo-surface PASS (0 issues), AMBIENT.md 8,070/8,192.
  • wiki:check --check-html PASS; density-trellis C12 and C13 updated alongside the code that made them stale, leaving C11 (from Route the front door to where the rules now live #189) and the seven fff40f4 left git-stale on purpose.
  • Every quotation re-read from the tree it cites, including all four module statuses and DEFAULT_SELECTION.

Nothing here is authorized beyond the rule and the framing repairs. No prompt bytes, no engine change. §5 of RESPONSE_ARTIFACT.md states that, and states plainly that the record has no enforcing surface.

OpenCnid added 7 commits July 24, 2026 16:10
Collaborator doctrine, July 24 2026, owner-approved for a framing pass: the
worker never works with gigabytes at a time. It answers questions ABOUT
gigabyte contexts, reading slices intelligently -- explicitly not everything --
and building a derived RESPONSE ARTIFACT over several turns and multiple
slices, without extracting more than needed. It never emits text to the
orchestrator and calls itself done. When bulk must be quoted it composes the
record programmatically and hands it over wholesale. For code editing the
repository is the response artifact.

The occasion was my own error. Ratifying the slice bound one commit earlier I
wrote, into config.py and CONFORMANCE section 2.3, that "a corpus arrives in
ceil(bytes / max_result_bytes) round trips, so 2 MiB is ~500 calls per GB" --
presenting the bound as the lever for bulk transfer. That describes an
operation the architecture does not have. DATA_MODEL section 6 is titled "The
bounded materialisation exception" and says so in its first paragraph: prefer
by-reference sinks; materialize is only for when the model itself must compute
over the bytes.

Repaired here, and the tell recorded with them: any sentence computing how much
of a corpus fits through the model is treating the model as the transport.

Three more of my own, found by a clean-room sweep. The CONFORMANCE layering
table asked "how large a corpus may the model work over?" and answered with the
guest's RLIMIT_AS -- locating the corpus inside the namespace, the one place
the handle model says it never is, and contradicting its own next sentence
since "potentially gigabytes" does not fit in 1 GiB. The table now separates
the corpus (host-side, bounded by nothing here) from the working set. SPEC
section 4.4 still carried the superseded July-22 frame rule as settled -- a
breadcrumb I failed to follow when I ratified its replacement. And a DATA_MODEL
section 6 quote was cited as section 7.

docs/architecture/RESPONSE_ARTIFACT.md is new: the doctrine, the mechanisms
that already hold it, and what four read-only sweeps found pulling the other
way. The mechanisms are real -- submit refuses a bare literal structurally,
handles keep the corpus out of the guest, locate/lines slice files, workspace
read() returns an index and never contents, MCP capture is harness-guaranteed.
What was missing is a frame tying them together, which is why every rule could
hold while the system got narrated as a bulk reader.

The findings are recorded and NOT acted on. The retrieval budget meters calls
rather than bytes, so a model optimising against it maximises bytes per fetch.
ITERATION BUDGET tells the worker it has very few turns and should combine
loading and computing into one block, against a max-iterations default of 5.
The corpus half of the runtime has no locate and no slice while the editing
half has both. fetch_texts is a public unmetered twin returning a live dict,
fewer keystrokes than the audited path. The word "artifact" reaches no model.
The default module opens with "Load the full question catalog in one query",
the module stating the discipline is active but out of DEFAULT_SELECTION, and
the module teaching the model to stop is retired.

Section 4 carries the design question I cannot settle: the doctrine's wholesale
hand-off is not reachable under the security model, because answer.submit sits
on the exfil ledger at 64 KiB, and nothing distinguishes a large legitimate
deliverable from bulk exfil -- submit("'\n'.join(b['text'] for b in blocks))
satisfies the pillar exactly while regurgitating.

Section 5 states what this authorizes: no prompt bytes (rule 16; the
collaborator's standing is that this gets prompted and enforced later), no
engine change, and no re-adjudication of TEST_TIME_TRAINING section 12.2, which
holds the opposite view as a dated owner correction and only the owner retires.
Reachability stated plainly: this record has no enforcing surface.

Verified: every quotation re-read from the tree it cites, including the four
module statuses and DEFAULT_SELECTION; pytest 1042; check:repo-surface PASS.
… needs

The target was written in records a construction decision never had to open,
and the build converged on the nearest familiar shape: a retrieval system with
a fact store bolted on. Rule 20 already names this failure for measurement --
reach for a comparison because it is closer to hand than a target. Rule 24 is
the same ordering, one level up, and it is numbered last and printed first
because burying a target where construction cannot see it is the error itself.

AMBIENT.md gains rule 24. Trellis is an agentic knowledge-work system over a
large context of domain-specific user information -- a toolset the user works
WITH, not a retrieval system with a fact store bolted on. Two sentences carry
it and one act falsifies each: a query produces a deliverable rather than a
reply, and the worker queries the corpus rather than transporting it. A schema
that can only carry a string cannot carry a deliverable, so a terminal action
requiring non-empty prose, an artifact envelope with one hardcoded text part,
and an answer sink rendering a single value each make the first false. The
collaborator wrote the charter sentence; the falsifiable clauses are what make
it a rule rather than a description. Fitting it took compressing this file's
least-decisive prose rather than growing past the bound (rule 22): 8070/8192.

docs/product/FEATURE_LIST.md is new -- eight capability groups, each row marked
shipped, built-unreachable, partial, or absent, written before security
hardening on purpose. A hardening pass over an unspecified feature set produces
a queue of follow-ups rather than a boundary.

What four read-only sweeps established, and what changed my read of it. The
substrate is healthy. The successor worker layer already HAS the corpus locate,
the bounded window, text-free get_ast_blocks, byte metering both directions and
a handle-typed llm_query context -- built, with no non-test caller, while
production spawns the legacy path. Grounded authoring is the response artifact
done correctly for one case: a run with zero retrieval affordance that writes a
multi-file directory. So the diagnosis holds where it matters and is narrower
than "rebuild": the doctrine is implemented one layer down and one layer over
from where the model actually lives.

The hole is the delivery contract, and it is text-only by schema at every
layer. A2A already carries a first-class artifacts array with typed parts and
renderArtifact hardcodes one text part; finish is invalid without non-empty
prose; submit renders one value. The envelope the target needs is already there,
empty.

Two corrections to records I wrote earlier today. answer.submit(H) is cited in
three places as the route for bulk content and DOES NOT EXIST -- submit takes an
expression string and renders a value, with no handle argument. An unbuilt
escape hatch reads exactly like a built one, which is why the doctrine's
wholesale hand-off looked merely capped. And the layering block in config.py
still asked what corpus size address space permits, locating the corpus inside
the namespace, which is the one place the handle model says it never is.

A defect worth its own line, found while assessing the turn budget: when a run
exhausts its iterations, rlms re-prompts the model over the whole transcript and
returns that as FINAL_ANSWER, bypassing the answer channel entirely -- no
literal check, no cap, no telemetry, no protocol violation. More turns spent
composing means more chance of landing on the guard-free path, so the iteration
budget cannot be widened before that is closed. FEATURE_LIST 2.7.

Verified: every quotation re-read from the tree it cites; pytest 1042; vitest
1416/119; check:repo-surface PASS (0 issues, AMBIENT.md 8070/8192);
wiki:check --check-html PASS.
C12 and C13 went stale against ab126f6, so their sections move with the code
they describe rather than being stamped later.

C13 takes rule 24, because a rule stating what is being built is a
self-description that construction has to be able to see -- which is the class's
whole subject. It records the placement argument (numbered last, printed first;
rule 20's ordering failure raised from measurement to construction), the byte
discipline that fitting it obeyed (least-decisive prose compressed rather than
appending past the bound, 8,070/8,192), and FEATURE_LIST.md as the consequence.

C12 takes both corrections. The corpus is bounded by nothing in the config
because it never enters the guest -- RLIMIT_AS bounds the working set, and the
earlier layering table asked what corpus size address space permits, putting the
corpus in the one place the handle model says it never is. And the sharper one:
answer.submit(H), the by-reference sink two records route bulk through, does not
exist, so the wholesale hand-off is unbuilt rather than capped. Also recorded
that charge_outbound fires only for the llm_query prompt, so the answer is not
on the exfil ledger, and THREAT_MODEL already calls the 64 KiB cap
output-shaping rather than a confidentiality control -- the collapse is
DATA_MODEL section 6 alone.

Verified: wiki:check clears C12 and C13, leaving C11 (from #189, not this
branch) and the seven fff40f4 left git-stale on purpose; --check-html PASS;
check:repo-surface PASS (0 issues).
Collaborator answers, July 24 2026, and one thing I got wrong twice.

TEST_TIME_TRAINING section 12.2 is WITHDRAWN from the audit. I read it as
doctrine holding that large REPL dumps are the intended workload. Section 12 is
a literature-applicability analysis; 12.2 argues that LaCT's long-context
results DO transfer to Trellis. That is a claim about whether a research finding
is relevant, not about desired behaviour, and reading the second as the first is
the whole error. TTT is not a counterweight to rule 24 -- it is a mechanism FOR
it: the harness composes a prompt from internal primitives, the composed prompt
sets the mode, the model self-plays over REPL data, and properly filtered
programmatic slicing is the REWARDED behaviour, scored by RLVCG
(arXiv:2607.19044). It targets a local open-weights model that does not exist
yet; TRELLIS_RLM_BACKEND is root-agent only and worker transport is explicitly
not configurable, which is why it reads forward-looking. Nothing needed
adjudicating.

Question 1 answered: the artifact is a Trellis-side object and A2A is one
rendering. 3.1 precedes 5.4.

Question 2 answered better than it was asked. An artifact CARRIES STANDING --
filed as a fact, a belief, or a doubt depending on purpose and what it carries.
So sections 3 and 6 are one subject, and artifact provenance rides the
machinery that already exists. DATA_MODEL section 7 already designs the shape:
doubts, beliefs and facts as three pre-allocated root handles at setup,
kind = graph-view, sliced by the algebra and never materialised whole. My
original question meant multi-tenant owner identity, which stays open as 1.6 and
is smaller than it looked, since ownership is a property of a filed artifact
rather than a prerequisite for having one.

Question 3, and the finding worth keeping: THE GATE IS ON A REMOVAL AND THE WANT
IS AN ADDITION. STANDING_MODEL.md was ratified July 20 2026 with a status line
authorizing no build, and its section 3 says what the withheld authorization
covers -- if the panel never moves standing, the promotion machinery reduces to
a findings recorder plus a user gate, and "that reduction removes shipped engine
surface", so deleting or rewriting shipped disposition code needs its own owner
dated entry and drills. Surfacing doubts/beliefs/facts as REPL state spaces is
not that. It is an addition, it is already designed, and no gate covers it. It
was never scheduled, not never approved.

Deferred capabilities are now marked PLACEHOLDER rather than absent, per the
collaborator: rough in the seam so the shape exists, land the capability when
the model connection does. 3.4 non-text artifact types and 4.5 non-text tool
results are the two.

Verified: pytest 1042; check:repo-surface PASS (0 issues).
Owner-approved July 24 2026. When a fan-out's finding would change what kind of
work follows -- rebuild versus repair, absent versus unreachable, defect versus
default -- one additional arm is spawned whose only task is to disprove the
reading the others are converging on, and whose ground block says so.

Narrow on purpose. Routine sweeps get no skeptic; the recurring charge is one
agent on scope-changing findings only, which is what makes it affordable enough
to actually hold.

The reason it is a separate arm rather than an instruction to the others:
siblings primed to find a problem find it, each one honestly, and their
agreement is then the shared prior restated rather than corroboration. Nothing
inside the fan-out can catch that, because no sibling is looking.

Provenance recorded with it, because the practice is worth less without the
case that produced it: three sweeps primed on "the build drifted toward
retrieval" found drift correctly everywhere they looked, and a fourth primed to
bound the claim found the capability the other three reported missing -- built,
and merely unreachable. Without that arm the session would have carried a
rebuild estimate for work already done.

Verified: check:repo-surface PASS (0 issues).
…the store

Owner rulings, July 24 2026, closing both open questions in the feature list.

Identity: one user, one instance. Ownership is the deployment boundary and is
never represented in the store -- which is why nothing in the substrate names an
owner and nothing needs to. Enterprise expands by cloning a base image of the
raw data, each clone owned by its user. 1.6 is closed as not applicable rather
than deferred.

Sequencing: artifacts now, with no recipient slot. I had proposed carrying that
slot as cheap insurance; under one-user-one-instance it earns nothing, because a
hedge against ambiguous recipients is only worth its column when more than one
recipient is possible. The migration story is image cloning, which carries
artifacts along with everything else and needs no backfill against append-only
rows.

The collaborator's clarification is the one that changes the shape of the list.
The artifact is NOT a terminal output. A run composes it, it is filed into the
user's own REPL store, and the judges promote and classify it -- so it lands as
a fact, a belief or a doubt, carries standing like anything else the user owns,
and becomes part of the corpus the next query slices. The output becomes input.

Two consequences recorded. Sections 3 and 6 are one pipeline rather than two
subjects: a deliverable that carries standing is not a different object from one
that carries content, it is the same object after the judges have seen it. And
3.5 needs no new provenance structure, because an artifact filed into the store
inherits the machinery every other stored thing already crosses.

Nothing in the list is now blocked on an owner decision. What remains is build
authorization, which is a different gate.

Verified: check:repo-surface PASS (0 issues).
… waive

Owner authorization, July 24 2026, for execution in a future session. The
ordering the list was written to defend is the ordering the authorization
follows: feature list, then build, then harden.

What it covers and what it does not is stated with it, because a list of rows
reads like a list of permissions. It authorizes building against this list. It
does not waive the gates that ride on KINDS of work -- prompt bytes still run
under rule 16, paid runs under rule 7, standing configuration under rule 21(b),
and any change that removes shipped engine surface still needs its own dated
entry. That last one is not hypothetical: section 6 exists in its current shape
because a gate on a removal was read as a gate on the whole epistemic layer, and
the addition it was blocking was never gated at all.

A row's presence here is permission to build it, never permission to skip the
gate its construction crosses.

Verified: check:repo-surface PASS (0 issues).
@OpenCnid
OpenCnid merged commit cd093c7 into master Jul 25, 2026
1 check passed
@OpenCnid
OpenCnid deleted the d/response-artifact-framing-7b23e1 branch July 25, 2026 00:34
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.

1 participant