Files
reverse-engineering-anything/docs/specs/agent-environments/write-derived-values/spec.md
T
38719a6fa9 feat(environment): explain values an application derives from other fields (#7025)
* feat(environment): explain values an application derives from other fields

Prompt-built environments withheld creates whose responses carry values the
application derives deterministically, which the write model kept as
constants or could not match across calls:

- A composed string is literal text plus parts read from the fields other
  rules write: a field's value, its slug, or a clock's calendar digits. A
  create composes a string only when another entity of the type spells it
  the same way and none spells it otherwise, and never from two sources
  serving could tell apart; an update composes an unsent change from members
  stored as sent and unchanged fields that also spell its value before the
  call. A composed field no longer pins the members it reads.
- A trimmed clock format drops trailing fraction zeros, as Go spells
  nanoseconds. It is learned from the type's values, a later create or a
  later update, and spreads to the plan's other clocks unless a value shows
  a fixed width.
- A large integer no entity of the type holds, among distinct ones of the
  same length and kind, is a generated unique value, served as a seeded
  integer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(environment): record the derived-values verification

Gates, tests, write plans over 69 recorded captures and served write tasks on the baseline and on this branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(environment): keep clock spellings, linked ids and word boundaries honest

- A later update's clocks take the plan's spelling, sibling-trimmed
  clocks included, wherever the call's values fit it, so an update whose
  later call trims only one of two clocks is served.
- A held value that ends its fraction in a zero keeps a create's clock
  at a fixed width, whatever order the held spellings come in.
- A large integer that another field of the created entity also holds
  is linked, as a repeated token is: it is never unique, and the create
  is withheld as unexplained-change.
- Composed parts are delimited by whole characters through the shared
  joinsBefore/joinsAfter, so an astral letter joins a match to its word.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(environment): keep a same-width fixed clock out of trimming

A held .123456780 beside a held .12345678 keeps the create's clock at
nine digits in either order; the cases fail on 8ce1127b5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(environment): check composed parts and clock fits before they shape a plan

- A composed string whose part has nothing to spell refuses the create
  or update through the apply Result instead of keeping a stale value.
- A composition learned on a later call is rebuilt from each earlier
  call's fields, so an earlier call that left the value otherwise
  contradicts it.
- An update adopts its fitted clock spellings only after the
  unknown-entity and contradiction checks, so a call on an entity an
  unmodelled write left unknown no longer trims a served plan's clock.
- Sibling trimming on a later create also checks that call's fields,
  so a sibling clock it shows with a trailing zero stays fixed-width.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(environment): split the derived-values view tests by rule

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(environment): keep fixed-width, zone and generated-integer evidence through a plan

- A plan keeps the first value that showed each clock at a fixed width,
  from held entities and every accepted create or update. No later fit
  or sibling trim widens that field, and a later call that shows it
  shorter is withheld.
- Two stamped clocks are one composed source only when they share a
  zone offset. A held entity that holds the target field as anything
  the parts do not spell, a non-string included, vetoes the
  composition. The token index is built once, and only when a string is
  left to compose.
- A generated integer that another field repeats as a number at any
  depth is linked. Compare treats two integers of one JSON kind and
  length under a unique rule as generated values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(setup): share registration prewarm host preparation

* fix(environment): retain write evidence and match trimmed response clocks

* fix(environment): withhold creates whose generated integer another string repeats

A unique integer whose digits show in another top-level string that no
template or composed rule rebuilds from it (an echoed serialText, or a
token like folder-<id>) withholds the create as unexplained-change,
since serving would seed the integer and keep the string. A templated
copy is still served.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(environment): hold later creates and compare to the composed and integer forms

- A later create whose response spells a composed field otherwise than
  the plan rebuilds it is withheld as unexplained-change.
- A unique field learned from a generated integer accepts only an
  integer of the same length and kind from a later create, as serving
  seeds one.
- Compare counts a composed field as equal when each side's response
  spells it from its own fields, which compare under their own rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(environment): preserve composed parts and unique generator families

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-25 05:06:21 +08:00

60 lines
4.4 KiB
Markdown

# Explain values an application derives from other fields
Issue: https://github.com/morluto/rea/issues/4933
## Outcome
Environments an agent built from a prompt withheld creates in three of five applications, each for a value the write
model could not explain, though the application derives it deterministically:
- Linkding's `web_archive_snapshot_url` is `https://web.archive.org/web/<creation time as YYYYMMDDhhmmss>/<sent url>`.
The plan kept it as a constant, which pinned `url` to its recorded value, so a later create with another URL was
refused.
- Grafana's folder `url` is `/dashboards/f/<uid>/<slug of the title>`, which pinned `uid` the same way, and its numeric
`id` is a large time-based integer the plan copied from the first create, which the second create's read-back
contradicted.
- Homebox, written in Go, spells nanosecond clocks with trailing fraction zeros dropped (`…34.38812218Z`), so a later
create's clock did not follow the format learned from the first.
## Behaviour
- **Composed strings.** A created field no other rule explains may be a `composed` string: literal text and parts read
from the fields other rules write, each a field's value, its slug, or a clock's calendar digits (`YYYYMMDDhhmmss`,
`YYYYMMDD`, `YYYY-MM-DD`, `YYYY/MM/DD`, in the clock's zone). Parts are found left to right, longest first, delimited
by non-alphanumerics; generated values may be short, other values need eight characters, as a copy does. A create
composes a string only when at least one other entity of the type spells it with the same parts and none spells it
otherwise, and never when one text comes from two sources serving could tell apart (two clocks the write stamps are
one source when they spell the same zone), and never when another entity holds the field as something other than the
parts spell, a non-string value included. An update's unsent change may be composed from members it stored as sent and
fields it left as they were, when the same parts also spell the value before the call and no other entity spells it
otherwise. Serving rebuilds the string from the written fields after every other rule and refuses a call when a part's
field holds nothing to spell, and a composed field no longer pins the members it reads. A composition learned on a
later call is checked against every earlier call, and a later create whose response spells a composed field otherwise
is withheld.
- **Trimmed clocks.** A clock format may be `trimmed`: its values differ only in how many fraction digits they show and
none ends a fraction in a zero. It is learned from the type's held values of the field, from a later create, and from
a later update; other clocks the plan stamps take the spelling too, and no clock takes it once a held entity, the
exemplar or any call the plan accepted showed the field at a fixed width; a later call that then shows it shorter is
withheld. `fraction` is the most digits shown, and serving drops trailing zeros and the point with them.
- **Generated integers.** A created integer of 10 to 20 digits that no entity of the type holds, where every held entity
holds a distinct one of the same length and JSON kind and none is a clock, is `unique`. Serving draws a seeded integer
of that length and kind that no held entity has. One that another field of the created entity also holds, as a value,
a number at any depth or a delimited part of a nested string, is not `unique`, and the create is withheld as
`unexplained-change`, since seeding cannot keep the two equal. A create is also withheld when another string holds its
digits and no `template` or `composed` rule rebuilds that string from it, or when a later create answers the field
with anything but an integer of the same length and kind. Compare treats two such integers of one JSON kind and length
under a `unique` rule as generated values.
Plans that need none of this are unchanged.
Later creates must retain the exemplar's unique-value family (UUID, integer with
the same digit count and JSON kind, or opaque token). Their recorded composed
fields must equal the values the plan rebuilds; simulation cannot replace a
contradictory captured value and then count that replacement as confirmation.
## Acceptance
- The prompt-built Linkding, Homebox and Grafana captures serve the creates and renames they withheld, and write
tasks that use them pass.
- No write tool of the 50 published captures or the earlier prompt-built captures goes from served to withheld.