agent: builder model: opus max_turns: 90 budget_usd: 18 —

Brief: yaml events, a walk of the parsed tree in the yaml-test-suite’s form (#928 step 4, first half)

Score: #928 step 4, the next step of the package; #1000 (which step 4 needed) is built (d715e425). This change touches only packages/yaml and needs no version raise and no CHANGELOG.md entry (ADR-yaml-1 D1).

Read docs/builder-facts.md, ADR-yaml-1 D4, D6 and D7 with its new paragraph (architect, 2026-10-31), and packages/yaml/src/main.nika (the tree types at the top, rule stream/Docs/NextDoc/AnyDoc, parse). The yaml-test-suite’s event form: https://github.com/yaml/yaml-test-suite (test.event files), summarised below. You do not need the network for it.

Pre-flight (added 2026-10-31, before the first run)

The architect’s probe of this step found #1063: a view field of a lent struct (n.anchor of a ref Node) stored in a new struct is refused NK2106, and in the package it cascades into NK1106 across the grammar. y22-1063-view-field-copy.md fixes it and runs before this brief. First run its Probe A (target/fast/nikaia run on the Word/again program there): it must print 1 hello. If it does not, stop: Result: blocked, Found: #1063 not fixed. An event’s anchor, tag and value are views of the input copied from the node (ADR-yaml-1 D4: nothing is copied), not .clone()d text.

To build

  1. The tree keeps what the walk needs (built in run 1, 2a303980; keep it as it is) (D7, new paragraph). Node gets pub flow: bool (true for a flow sequence or mapping, false for everything else); every Node { .. } in the grammar sets it. A pub struct Document { pub root: Node, pub start: bool, pub end: bool } (--- written, ... written after it), and pub fn documents(input: ref Bytes; limits: Limits = default_limits()) -> Vec[Document] sync throws, with the size and depth errors parse gives today. parse becomes documents with each root taken out (no second parse, no copy of a node). A ... belongs to the document before it. The existing 14 package tests keep their output byte for byte. Commit.
  2. Events (D7). pub enum / pub struct for an event (names yours): stream start/end, document start/end (explicit or not), sequence and mapping start (block or flow) and end, scalar (style, its value through text()), alias; each with its anchor, tag and span (start, end byte offsets). pub fn events(docs: ref Vec[Document]) -> Vec[Event] (or the input as argument, if the views make that the plainer call), and pub fn event_line(e: ref Event) -> String, the suite’s line form:
    • +STR, -STR; +DOC or +DOC ---; -DOC or -DOC ...;
    • +SEQ, +SEQ [] (flow), -SEQ; +MAP, +MAP {} (flow), -MAP;
    • =VAL followed by the style mark and the value (a Value::Str gives its Scalar’s style and text(); every other scalar node its Node.raw and Node.style, y23: =VAL :~, =VAL :True, =VAL <tag:yaml.org,2002:int> "1): : plain, ' single, " double, | literal, > folded; in the value \ is \\, a line break \n, a tab \t, a backspace \b, a carriage return \r;
    • =ALI *name; an anchor is written &name and a tag <tag> (the tag as the tree keeps it, between angle brackets) after the +SEQ/+MAP/=VAL word and before the value, e.g. +MAP {} &a <tag:yaml.org,2002:map>, =VAL &x :1. If the tree keeps a tag in its short form (!!str) rather than resolved (tag:yaml.org,2002:str), write what the tree has (<!!str>, a verbatim !<t> as <t>) and say so in Body:, not Deviation: (architect, before run 3); resolving it is a later step of #928.
    • An empty node (null with no text) is =VAL :.
  3. Tests: packages/yaml/tests/events.nika + .stdout: block and flow collections, every scalar style, a document with and without ---/..., two documents, an anchor, an alias and a tag, nested collections; and one line per event printed with its span for one small input. Compare by hand with the suite’s form above.

load (aliases expanded, duplicate keys, the alias limit) is the next brief, not this one.

If a form the package needs is missing or refused in the compiler, the lowering or std (no ADR refusing it), stop: Result: blocked, Found: the gap with a probe of a few lines, Needs: architect decision. Do not write around it.

Run 2 (2026-10-31): what changed

Run 1 built step 1 (2a303980: Node.flow, Document, documents, test document_markers) and stopped before step 2: the tree dropped the text and style of a scalar that resolves to Null, Bool, Int or Float (~ and null one node, !!int "1" without its quotes). The architect decided it (ADR-yaml-1 D7, last paragraph): Node has pub raw: String and pub style: Style for every scalar node, built by y23-scalar-written.md just before this run. Pre-flight for run 2, instead of y22’s Probe A: rg -n "pub raw: String|pub style: Style" packages/yaml/src/main.nika shows both on Node, and packages/yaml/tests/scalar_written.stdout exists; if not, stop: Result: blocked, Found: y23 not built. Build steps 2 and 3 only. Write tests/events.nika before the first package run and fill its .stdout with --bless in that run (one run is 3-4 minutes).

Run 3: what changed (architect, 2026-10-31)

Run 2 drafted steps 2 and 3 (local branch wip/y21-events, 0433d662, also on origin: events, event_line, tests/events.nika, fmt-clean, .stdout not blessed) and stopped on three view-checker defects, now fixed by the briefs before this run: #1070 (a by-value field-less enum beside a view, y24), #1071 (a list of views returned as a literal or grown with extend, y25), #1072 (a view field off a match payload, y26). Pre-flight: the probes of docs/briefs/yaml/y2{4,5,6}-*.md print their wanted lines on target/fast/nikaia (rebuild it with cargo build --profile fast -p nikaia first; the session hook’s binary may predate the fixes); if one does not, stop: Result: blocked, Found: <brief> not on develop. Then take the draft: git diff 6269eca3 0433d662 -- packages/yaml | git apply (only packages/yaml/src/main.nika and packages/yaml/tests/events.nika; not the probe files), nikaia check packages/yaml/src/main.nika (one file, no --project), and finish steps 2 and 3 there. A mutable parameter is written mut out: Vec[T]; views of a ref node cannot go into a mut out-parameter (NK2302 by rule), so the walk returns its events. Write tests/events.nika’s .stdout with --bless in the first package run and check it by hand.

Run 4: what changed (architect, 2026-10-31)

Run 3 finished the draft (local branch wip/y21-events at 1c1199d6: Event.value always a view, Node.raw or an alias’s name; a new pub text: String? holds the owned text(s) of a Value::Str, null for every other event; event_line writes text if set, else value) and stopped on one view-checker defect: walk returns match n.value { .. } whose arms are lists of views, refused NK2302. Filed as #1085, fixed by y28-1085-views-back-through-if-match.md just before this run. The architect checked the rest: with walk rewritten to push into a local, the draft checks, builds, and tests/events.nika runs and prints the suite’s form. Keep walk as the draft writes it (return match); do not rewrite it.

Pre-flight (inline, wanted 1 hello; rebuild target/fast/nikaia with cargo build --profile fast -p nikaia first): the program under Probe in y28-1085-views-back-through-if-match.md. If it does not print 1 hello, stop: Result: blocked, Found: #1085 not on develop. Then:

  1. git diff 6269eca3 1c1199d6 -- packages/yaml/src/main.nika packages/yaml/tests/events.nika | git apply, then target/fast/nikaia check packages/yaml/src/main.nika: no error. If a view-checker refusal remains, narrow it in two probes, the shape as return x and as let r = x; return r, and report it as Found:.
  2. touch packages/yaml/tests/events.stdout, then one package run with --bless (an output test needs its .stdout to exist); check the blessed lines by hand against step 2’s form; then the package gate. Commit (steps 2 and 3). The branch wip/y21-events stays where it is.

Rules (CLAUDE.md; this block is pasted into every brief, also a fix-forward)

Report (at most 15 lines, to exactly /home/user/Nikaia/docs/briefs/yaml/y21-events.md.report.md)

Fields of docs/architect.md, Briefs and reports: Result: done|noop|partial|blocked (the bare word alone on that line: Result: done, never a summary after it, which cuts the batch, b869a 2026-10-27; Owner: is a question for the owner or none, never a role), Files, Commit, Body (optional, one paragraph for the commit message), Fixes, Pushed, Tests, Gate (green|red), Deviation, Found, Needs, Changelog, Owner, Disk freed, and for a move Rs2nika: (the kept N of M lines of rs2nika --score, then the three costliest hand edits; none for a task that moves no Rust, none (redesign) for a brief with Shape: redesign and no Convert: line). none where nothing, and then the bare word: Deviation: none (a note) cuts the batch (batch.nika compares exactly); a note goes into the commit message. Found: is only for a defect outside your change (it cuts the batch); a process event such as another session resetting or rewriting your files is no Found:, it goes under Needs: (m3a 2026-10-28); a converter draft that came out wrong is no Found:, it is one of the costliest edits under Rs2nika:, which the converter lane reads (e12-4b 2026-10-27); how you solved your own step goes into the commit message. Deviation: is only a step of the brief built otherwise than written or not built (a choice the brief left to you, such as keep what X needs and say so, is no deviation: it goes into the commit message; nor is building two steps in one commit when every step is built, e12-3a 2026-10-27, nor a step another commit on develop already built, shown by your test failing with that commit’s change reverted, b889 2026-10-27: name the commit in Body:, nor a test’s expected .stdout/.stderr taken from what the program really prints where the brief’s sketch of it was short or wrong, b934 2026-10-29: say so in Body:, nor a lowering that follows the ADR governing it where the brief’s expected lowering contradicts that ADR, b933 2026-10-29: name the ADR in Body:, nor a lowering other than the brief’s where rustc cannot take the brief’s, b1029 2026-10-31: say why in Body:, nor re-keying an allow-list entry (KNOWN) whose hash changed for the same program and the same reason, b-fixforward-sweep2 2026-10-28: say so in Body:, nor an existing test’s expected .stdout/.stderr updated because your change rightly changes the message it prints, b1012b 2026-10-31: name the test in Body:); how you verified (e.g. a test not run against the unfixed compiler) goes under Tests:. A noop says why under Tests: (what was probed), not under Deviation:. Final answer, one line: done <sha>, report <path> (or BLOCKED: ... / PUSH REJECTED ...).

Attribution: Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_01UVxJDveRM5qKZKyCqq6Y24

This site is open source. Improve this page.