",
+ " | ",
+ "",
+ " | ",
+ " | ",
+ " | ",
+ " | ",
+ ] {
+ let result = observe_ae13b4(
+ source,
+ ObservationRequest::NotRequested,
+ ObservationRequest::Capture { capacity: 32 },
+ );
+ assert!(
+ unsupported_identities(&result).contains(
+ &Feature::GenerateImpliedEndTagsAndCheckCurrentNodeBeforeClosingTableCell
+ ),
+ "source={source}"
+ );
+ }
+ }
+
+ #[test]
+ fn every_caption_close_caller_observes_exact_identity_and_reprocessing() {
+ use crate::html5::shared::{
+ ObservedInsertionMode as Mode, TransitionTokenSummary,
+ TreeConstructionUnsupportedFeature as Feature, TreeDispatchPath,
+ UnsupportedFeatureEvent,
+ };
+
+ for (token, token_name, start_tag, reprocesses) in [
+ ("", "caption", false, false),
+ ("", "colgroup", true, true),
+ (" ", "table", false, true),
+ ] {
+ for nested in [false, true] {
+ let source = if nested {
+ format!("x{token}")
+ } else {
+ format!(" {token}")
+ };
+ let observed = observe_ae13b4_input(
+ ParserObservationInput::Utf8(&source),
+ ObservationRequest::Capture { capacity: 128 },
+ ObservationRequest::Capture { capacity: 8 },
+ ObservationRequest::Capture { capacity: 256 },
+ );
+ let baseline = observe_ae13b4_input(
+ ParserObservationInput::Utf8(&source),
+ ObservationRequest::Capture { capacity: 128 },
+ ObservationRequest::NotRequested,
+ ObservationRequest::Capture { capacity: 256 },
+ );
+
+ assert_eq!(observed.tree, baseline.tree, "source={source}");
+ assert_eq!(
+ observed.transitions, baseline.transitions,
+ "source={source}"
+ );
+ assert_eq!(
+ observed.parse_errors, baseline.parse_errors,
+ "source={source}"
+ );
+
+ let events = captured(&observed.unsupported_features);
+ if nested {
+ assert_eq!(events.len(), 1, "source={source}");
+ let UnsupportedFeatureEvent::TreeConstruction {
+ occurrence,
+ feature,
+ ..
+ } = &events[0];
+ assert_eq!(*occurrence, 1, "source={source}");
+ assert_eq!(
+ *feature,
+ Feature::GenerateImpliedEndTagsAndCheckCurrentNodeBeforeClosingCaption,
+ "source={source}"
+ );
+ } else {
+ assert!(events.is_empty(), "source={source}");
+ }
+
+ let attempts = captured(&observed.transitions)
+ .iter()
+ .filter(|event| match event.token.as_ref() {
+ TransitionTokenSummary::StartTag { name, .. } => {
+ start_tag && name == token_name
+ }
+ TransitionTokenSummary::EndTag { name } => !start_tag && name == token_name,
+ _ => false,
+ })
+ .collect::>();
+ let expected_attempts = if reprocesses { 2 } else { 1 };
+ assert_eq!(attempts.len(), expected_attempts, "source={source}");
+ assert_eq!(
+ attempts[0].dispatch_path,
+ TreeDispatchPath::HtmlInsertionMode(Mode::InCaption),
+ "source={source}"
+ );
+ assert!(!attempts[0].reprocessed, "source={source}");
+ if reprocesses {
+ assert_eq!(
+ attempts[1].dispatch_path,
+ TreeDispatchPath::HtmlInsertionMode(Mode::InTable),
+ "source={source}"
+ );
+ assert!(attempts[1].reprocessed, "source={source}");
+ }
+ }
+ }
+
+ let whole_source = "";
+ let chunks = [""];
+ let whole = observe_ae13b4_input(
+ ParserObservationInput::Utf8(whole_source),
+ ObservationRequest::Capture { capacity: 128 },
+ ObservationRequest::Capture { capacity: 8 },
+ ObservationRequest::Capture { capacity: 256 },
+ );
+ let chunked = observe_ae13b4_input(
+ ParserObservationInput::Utf8Chunks(&chunks),
+ ObservationRequest::Capture { capacity: 128 },
+ ObservationRequest::Capture { capacity: 8 },
+ ObservationRequest::Capture { capacity: 256 },
+ );
+ assert_eq!(whole.unsupported_features, chunked.unsupported_features);
+ assert_eq!(whole.transitions, chunked.transitions);
+ assert_eq!(whole.parse_errors, chunked.parse_errors);
+ assert_eq!(whole.tree, chunked.tree);
+ }
+
+ #[test]
+ fn ae13b4_observations_are_whole_chunked_equal_and_do_not_change_tree_output() {
+ let chunks = ["", " | `, no cell in table scope preserves the existing
+parse-error-and-ignore behavior and emits no unsupported event. An opposite
+scoped cell emits only `RequireSameNamedTableCellInScopeForEndTag`; it does not
+also claim downstream close preparation, because the Standard algorithm would
+stop at the failed same-name guard. A matching current cell emits no event. A
+matching non-current cell emits the compound preparation identity.
+Table-structure-driven closure has no failed same-name guard and emits the
+compound identity when the exact scoped cell `PatchKey` is not current.
+Caption closure uses the same exact-key rule for its compound preparation
+identity.
+
+General causality rule: an unsupported event is not emitted for a downstream
+algorithm step that would be unreachable if an earlier missing guard for the
+same token were implemented correctly.
+
+These events replace the four former attribute-merge, caption-close, and
+mismatched-cell implementation-diagnostic identities. Independent
+authored-input parse errors remain. Ordinary implementation diagnostics,
+configured limits, parser guardrails, operating-resource exhaustion, engine
+invariants, fixture limitations, unsupported execution targets, and deliberate
+fully implemented Borrowser deviations remain separate categories.
+
+All recorder failures share one first-observed
+`ParserObservationFailure::{Capture, Invariant}` slot. Observer-only token
+canonicalization, attribute comparison, or live-element lookup failure is
+latched without changing parser control flow. A separately occurring parser
+fatal remains authoritative and suppresses canonical observation output.
+Standalone-tokenizer transition requests are
+`NotApplicable(StandaloneTokenizerRun)`; unsupported-feature requests remain
+applicable because future exact preprocessing/tokenizer variants may use that
+surface. Tree-construction unsupported events can occur only when document
+tree construction actually runs. Unrequested surfaces remain `NotRequested`.
+
+AE13b4 adds no serializer, fixture sidecar, adapter, corpus migration, final
+invariant execution, or implementation of the observed missing algorithms.
+
+### Approved follow-up backlog
+
+Milestone: **AE follow-up — Remaining observed tree-construction conformance**
+
+Description: implement the exact tree-construction semantics exposed by
+AE13b4 while preserving parser ownership, production dispatch, patch/stack/AFE
+invariants, and whole-versus-chunked parity. The milestone does not add
+scripting, frameset insertion modes, fragment parsing, public DOM APIs, or
+runtime behavior.
+
+- **Implement attribute merging for repeated html start tags.** Implement the
+ applicable first-wins expanded-name merge into the authoritative existing
+ parser-created root element, preserving template suppression, patch/live-tree
+ consistency, source attribute order, and deterministic chunk parity.
+- **Implement attribute merging for repeated body start tags.** Implement the
+ applicable first-wins expanded-name merge into the authoritative second-stack
+ HTML body element, preserving template and stack-state exceptions,
+ patch/live-tree consistency, source order, and chunk parity.
+- **Mark frameset not ok for repeated body start tags.** Implement the
+ applicable repeated-body `frameset_ok = false` transition independently of
+ attribute merging, respecting template and second-stack-entry body
+ exceptions. Do not add frameset insertion modes or frameset element parsing.
+- **Implement complete table-cell end-tag and close preparation.** Implement
+ same-named `td`/`th` table-scope validation; parse-error-and-ignore behavior
+ for mismatched explicit cell end tags; implied-end-tag generation before
+ valid cell closure; the post-generation current-node check; and all explicit
+ and table-structure-driven `close_cell` paths. Preserve stack, AFE,
+ insertion-mode, patch, transition, and whole/chunk invariants.
+- **Implement complete caption close preparation.** Generate the required
+ implied end tags before caption closure, perform the post-generation
+ current-node check and parse error, and preserve caption scope, stack, AFE,
+ patch, transition, and whole/chunk invariants for explicit and
+ table-structure-driven closure.
+
+Milestone: **AE follow-up — Parser observation resource accounting**
+
+Description: complete parser observation memory accounting without changing
+semantic event identity or production parsing.
+
+- **Add byte-bounded parser observation payload policies.** Add explicit,
+ independently configured retained-string byte capacities for parser
+ observation surfaces while preserving event-count capacity, production-order
+ occurrences, drop accounting, passive failures, lazy logical-token
+ canonicalization, shared immutable summaries, and deterministic conformance
+ projection. Do not add serializers or infer events after parsing.
+
## Exact input and path boundary
All inputs are loaded with `fs::read`; the loader never trims or normalizes
diff --git a/docs/html5/ae8-specialized-table-tree-construction-contract.md b/docs/html5/ae8-specialized-table-tree-construction-contract.md
index 69336ab7..210898e5 100644
--- a/docs/html5/ae8-specialized-table-tree-construction-contract.md
+++ b/docs/html5/ae8-specialized-table-tree-construction-contract.md
@@ -143,11 +143,17 @@ Entering `td` or `th`:
Closing a cell, whether explicit or parser-recovery-driven:
- finds the current table cell in table scope;
-- performs the supported implied-end-tag stack cleanup by closing through the
- table-scope path;
+- closes through that scoped cell using Borrowser's deterministic substitute
+ stack path;
- clears active formatting entries back to the last marker;
- switches to `InRow`.
+AE8 does not implement the Standard's same-named `td`/`th` scope guard for
+explicit end tags, implied-end-tag generation before cell closure, or the
+post-generation current-node check. It likewise does not implement caption
+close preparation. AE13b4 observes those exact production omissions without
+changing AE8's substitute tree, stack, AFE, insertion mode, or parse errors.
+
AE8 does not introduce layout cell concepts into the parser.
AE10 adds marker kind/owner diagnostics without changing AE8's last-marker
boundary semantics.
diff --git a/docs/html5/html5-core-v0.md b/docs/html5/html5-core-v0.md
index 7a8a60e1..d2d68f2d 100644
--- a/docs/html5/html5-core-v0.md
+++ b/docs/html5/html5-core-v0.md
@@ -198,7 +198,11 @@ Core v0 tree-builder partial-scope guards:
- `TB-ALGO-AAA` (`MVP_PARTIAL`) is limited to Borrowser's supported
formatting-element set and representative deterministic recovery fixtures.
This does not claim full WHATWG adoption-agency conformance.
-- `TB-ALGO-REPROCESS` guarantees that reprocessing reuses the same token instance and does not emit duplicate patches for a single logical token unless explicitly required by the spec algorithm.
+- `TB-ALGO-REPROCESS` guarantees that reprocessing reuses the same logical
+ token and does not emit duplicate patches for a single semantic action.
+ AE13b4 observes only central-driver attempts. Internal calls between rule
+ sets are delegation, not redispatch; foreign-to-HTML fallback is an explicit
+ one-shot central `HtmlRulesOnly` route.
### Text Coalescing Policy (Core v0)
@@ -331,12 +335,13 @@ Core v0 guarantees:
### Parse-Error Diagnostics
-Core v0 parser diagnostics are deterministic internal regression/debug data:
+Core v0 parser events are deterministic internal regression/debug data:
-- one `DocumentParseContext` diagnostic fanout owns counters, the independent
+- one neutral `DocumentParseContext` event sink owns counters, the independent
parse-error and implementation-diagnostic occurrence sequences, bounded
- canonical retention, dropped counts, and optional legacy projection for
- preprocessing, tokenizer, and tree-construction production rules;
+ canonical diagnostic retention, parser observations, dropped counts, and
+ optional legacy diagnostic projection. Transition and unsupported-feature
+ observations are not diagnostics and have independent sequences/capacities;
- tokenizer-origin malformed input records exact-position legacy `ParseError`
entries where representable. Tree-construction canonical events currently
use `Unavailable(ParserDidNotProvidePosition)` and are not projected with a
@@ -517,7 +522,10 @@ Core v0 stance:
`thead`, `tfoot`, `tr`, `td`, and `th`.
- supported omitted wrappers, malformed row/cell/body recovery, pending
table-character-token handling, and foster-parent insertion locations are
- parser-owned behavior.
+ parser-owned deterministic behavior. This does not claim the same-named
+ `td`/`th` end-tag guard, implied-end-tag preparation/current-node check for
+ table-cell closure, or caption-close preparation; AE13b4 observes those
+ exact omissions without implementing them.
- unsupported table interactions still require robust fallback:
- parser MUST remain deterministic,
- parser MUST preserve core invariants (SOE/patch ordering),
@@ -547,7 +555,19 @@ Core v0 stance:
wrap, and counter-backed depth-16/depth-256 fixtures prove linear aggregate
EOF close/owner/reset work with O(1) auxiliary recovery memory. Contents are
preserved in the centralized full-model traversal and inert to active
- consumers.
+ consumers. AE13b4 classifies shared-template interception as one central
+ `SharedTemplateRules` attempt; its internal InHead/InBody delegation creates
+ no extra attempt, and template EOF unwind remains outside the attempt trace.
+
+- AE13b4 adds parser-owned dispatch-attempt and exact unsupported-feature
+ observations. The central driver records ordinary HTML, shared-template,
+ Text-mode, and foreign attempts with before/after insertion modes and
+ same-token redispatch identity. Foreign breakout and HTML fallback use a
+ one-shot HTML-rules-only route rather than hidden handler calls. The exact
+ unsupported identities cover repeated html/body attribute merging, repeated
+ body `frameset_ok`, table-cell same-name/close preparation, and caption close
+ preparation. These observations do not implement the six missing algorithms.
+ Event capacity bounds retained event count, not retained token-string bytes.
- AE13b2.2a defines allocation-free parser fatal identities and first-failure
terminal latching for live `Html5ParseSession` work. Construction failures
@@ -591,6 +611,9 @@ The following are intentionally not part of the Core v0 guarantee:
CharacterData mutation, cloning, public mutation, and broader DOM PI
validity
- `PLAINTEXT`, frameset insertion modes, and fragment parsing for AE12
+ - repeated html/body attribute merging; repeated-body `frameset_ok = false`;
+ same-named table-cell end-tag recovery; cell/caption implied-end-tag and
+ post-generation current-node preparation observed by AE13b4
Policy classification requirements:
diff --git a/docs/html5/invariants.md b/docs/html5/invariants.md
index 971b85fa..a1afe2d5 100644
--- a/docs/html5/invariants.md
+++ b/docs/html5/invariants.md
@@ -181,6 +181,10 @@ Table cell and AFE interaction:
- closing a cell, explicit or implied, clears AFE entries back to the last
marker;
- cell close recovery must not expand into unrelated adoption-agency behavior.
+- AE13b4 observes, but does not implement, the same-named explicit cell-end-tag
+ guard and implied-end-tag/current-node preparation. If the missing same-name
+ guard would have ignored a token, no downstream close-preparation omission is
+ reported for that token.
## AE9a Form And Void-Insertion Invariants
@@ -304,11 +308,43 @@ Table cell and AFE interaction:
foster parenting, and other adjusted insertion locations.
- Breakout reprocesses the exact token only after a stack change establishes
progress. Foreign end-tag scanning never corrupts stack caches.
+- Foreign breakout and end-tag HTML fallback return a one-shot central
+ `HtmlRulesOnly` directive; foreign handlers never call HTML handlers
+ directly. Selection scope participates in exact cycle identity but a
+ route-only scope change is not generic semantic progress. A forced HTML
+ attempt cannot force the same route again.
- Unknown foreign elements retain their inherited foreign namespace. Results,
patches, errors, and attribute order do not depend on chunk boundaries.
- Layout inability cannot alter DOM/style truth; unsupported SVG/MathML roots
suppress complete box subtrees at the centralized Layout decision boundary.
+## AE13b4 Parser Observation Invariants
+
+- One tree transition is one central-driver invocation of one selected
+ top-level family: ordinary HTML insertion mode, shared template rules,
+ foreign content, or Text mode. Internal rule-set delegation is not an
+ additional attempt.
+- The central driver captures committed insertion mode before selection and
+ after outcome validation/application. A handler returning
+ `Reprocess(next_mode)` may leave the mode unchanged or already set it to
+ `next_mode`; any third mode is an engine invariant.
+- A logical token is finalized for self-closing semantics exactly once after
+ its terminal attempt. Its retained attempts share one lazily canonicalized
+ immutable token summary.
+- Transition and unsupported-feature surfaces independently own request state,
+ capacity, occurrence sequence, retained prefix, drop count, and overflow
+ identity. No cross-surface timeline exists. Capacity zero and exhausted
+ capacity still reserve occurrences and count drops without constructing
+ owned transition payloads.
+- Transition capacity bounds event count, not retained token-string bytes.
+- All observation failures latch through one first-observed
+ `ParserObservationFailure` slot. Observer-only failure remains passive;
+ independently occurring parser fatal failure remains authoritative and
+ suppresses canonical observation output.
+- Unsupported observations originate only at the exact production fallback.
+ A downstream omission is not reported when a missing earlier guard would
+ have made that downstream step unreachable for the same token.
+
## AE12 processing-instruction invariants
- Ordinary PI recognition is entered only through Data/TagOpen. Borrowser's
diff --git a/docs/html5/spec-matrix-treebuilder.md b/docs/html5/spec-matrix-treebuilder.md
index 8636b080..c41178db 100644
--- a/docs/html5/spec-matrix-treebuilder.md
+++ b/docs/html5/spec-matrix-treebuilder.md
@@ -52,12 +52,13 @@ It defines HTML5 Core v0 tree-builder scope and explicitly records deferred and
- AE13b2 exposes a feature-gated in-memory scalar observation, not a patch,
DOM API, or serialized fixture sidecar.
-## Tree-construction diagnostic contract
+## Tree-construction event contract
-- `DocumentParseContext` owns one shared diagnostic fanout and the independent
- parse-error and implementation-diagnostic occurrence sequences.
+- `DocumentParseContext` owns one neutral parser event sink. It owns diagnostic
+ counters/projection and the parser observation recorder without categorizing
+ transitions or unsupported-feature observations as diagnostics.
- `TreeBuilderProcessContext` is the one-token borrow boundary for the atom
- table and tree diagnostic sink; `process`/`push_token` keep borrowed tokens,
+ table and tree event sink; `process`/`push_token` keep borrowed tokens,
`TextResolver`, `PatchSink`, `TreeBuilderStepResult`, tokenizer controls, and
`TreeBuilderError`.
- HTML parse errors, Borrowser implementation diagnostics, configured
@@ -81,6 +82,11 @@ It defines HTML5 Core v0 tree-builder scope and explicitly records deferred and
finite fail-on-incomplete capture, and projects only typed tree parse errors.
It does not establish a combined parse/implementation timeline or affect
patch goldens.
+- AE13b4 transition and unsupported-feature surfaces have independent
+ requested state, capacities, occurrences, retained prefixes, and drop
+ accounting. There is no global event timeline. Parser-owned semantic types
+ are always compiled; `html::conformance` only re-exports and projects them.
+ Transition event capacity is not a retained-string byte budget.
## Historical Repository Baseline (Before D2 Execution)
@@ -109,11 +115,11 @@ It defines HTML5 Core v0 tree-builder scope and explicitly records deferred and
| `TB-MODE-TEXT` | MVP_PARTIAL | `Text` | `#the-text-insertion-mode` | `mod.rs`, `modes.rs`, `text_mode.rs` | Current coverage: `tree_builder/tests/text_mode.rs`; planned fixture umbrella: `tb-text-mode-core`. | Return-to-original-mode mechanics, mismatched end tags, and EOF in text mode. | `tb-text-mode-core` | Core-v0 text-mode routing for title/textarea/style and the dedicated script tokenizer family; parser execution/pause behavior remains out of scope. |
| `TB-MODE-IN-TABLE` | MVP_PARTIAL | `In table` | `#parsing-main-intable` | `tree_builder/table/in_table.rs`, `insert/location.rs`, `stack/foster.rs` | Current: `ae8-*`, `i10-table-*`, `i3-in-table-*`; unit: `table_modes.rs`. | caption/colgroup/row-group/row/cell dispatch, implied wrappers, nested table recovery, foster-parented non-table content. | `tb-ae8-in-table` | AE8 supported static table construction routes table tokens through explicit table mode instead of generic in-body nesting. |
| `TB-MODE-IN-TABLE-TEXT` | MVP_PARTIAL | `In table text` | `#parsing-main-intabletext` | `tree_builder/table/in_table_text.rs`, `table/state.rs`, `table/delegation.rs` | Current: `ae8-pending-table-text-eof`, `ae8-foster-text-and-element`; unit: table-text return-mode tests. | Chunk-safe pending character buffering, return-mode restoration, EOF flush, foster-parenting non-space runs. | `tb-ae8-in-table-text` | Needed so table whitespace and non-space table text are processed through parser-owned pending state. |
-| `TB-MODE-IN-CAPTION` | MVP_PARTIAL | `In caption` | `#parsing-main-incaption` | `tree_builder/table/in_caption.rs`, `table/close.rs` | Current: `i4-caption-colgroup-transition`; unit: `table_caption_colgroup.rs`. | Caption close, conflicting table-structure tokens, AFE marker cleanup. | `tb-ae8-in-caption` | Caption content delegates to body rules until a table-structure token closes and reprocesses. |
+| `TB-MODE-IN-CAPTION` | MVP_PARTIAL | `In caption` | `#parsing-main-incaption` | `tree_builder/table/in_caption.rs`, `table/close.rs` | Current: `i4-caption-colgroup-transition`; unit: `table_caption_colgroup.rs`; AE13b4 exact unsupported observation. | Caption close, conflicting table-structure tokens, AFE marker cleanup; implied-end-tag/current-node close preparation remains unimplemented. | `tb-ae8-in-caption` | Caption content delegates to body rules until a table-structure token closes and reprocesses. |
| `TB-MODE-IN-COLUMN-GROUP` | MVP_PARTIAL | `In column group` | `#parsing-main-incolgroup` | `tree_builder/table/in_column_group.rs`, `table/close.rs` | Current: `ae8-basic-explicit-table`, `i4-colgroup-*`; unit: `table_caption_colgroup.rs`. | `col` insertion, missing ``, non-space recovery into table foster-parenting. | `tb-ae8-in-column-group` | Required for deterministic parser-created `colgroup`/`col` structure. |
| `TB-MODE-IN-TABLE-BODY` | MVP_PARTIAL | `In table body` | `#parsing-main-intbody` | `tree_builder/table/in_table_body.rs`, `table/scope.rs`, `table/close.rs` | Current: `ae8-multiple-bodies`, `ae8-implied-row-direct-cell`; unit: `table_body_row.rs`. | row insertion, implied row for cells, row-group transitions, table end recovery. | `tb-ae8-in-table-body` | Owns row-group context instead of encoding row-group behavior in generic element insertion. |
| `TB-MODE-IN-ROW` | MVP_PARTIAL | `In row` | `#parsing-main-intr` | `tree_builder/table/in_row.rs`, `table/close.rs` | Current: `ae8-malformed-row-and-cell-recovery`, `i5-stray-tr`; unit: `table_body_row.rs`. | cell insertion, conflicting row starts, row closure, row-group/table boundaries. | `tb-ae8-in-row` | Owns row context and cell transition behavior. |
-| `TB-MODE-IN-CELL` | MVP_PARTIAL | `In cell` | `#parsing-main-intd` | `tree_builder/table/in_cell.rs`, `table/close.rs` | Current: `ae8-malformed-row-and-cell-recovery`, `i6-*`; unit: `table_cell.rs`. | explicit/mismatched cell end tags, implied cell close, AFE marker clearing, nested table support. | `tb-ae8-in-cell` | Owns table-cell recovery without introducing layout-cell concepts. |
+| `TB-MODE-IN-CELL` | MVP_PARTIAL | `In cell` | `#parsing-main-intd` | `tree_builder/table/in_cell.rs`, `table/close.rs` | Current: `ae8-malformed-row-and-cell-recovery`, `i6-*`; unit: `table_cell.rs`; AE13b4 exact unsupported observations. | deterministic explicit/mismatched cell substitute recovery and AFE clearing; same-name guard plus implied-end-tag/current-node close preparation remain unimplemented. | `tb-ae8-in-cell` | Owns a partial table-cell recovery boundary without introducing layout-cell concepts. |
| `TB-MODE-IN-TEMPLATE` | MVP_PARTIAL | `In template` | `#parsing-main-intemplate` | `tree_builder/dispatch/template.rs`, `tree_builder/template_state.rs`, `tree_builder/modes.rs` | Current local `ae10-*`; pinned WPT `template-*`; unit/session template tests. | category delegation, owner-mode replacement, same-token reprocessing, nested close and EOF unwind. | `tb-ae10-template-construction` | AE10 static ordinary-template subset with typed contents; no declarative shadow DOM or public template APIs. |
## `TB-MODE-IN-HEAD` Core v0 Partial Scope
@@ -136,7 +142,7 @@ Explicitly deferred from Core v0 `In head`:
| ID | Tier | Algorithm / structure | Spec anchor(s) | Implementation mapping | Test mapping (current + planned) | Key edge cases | Acceptance placeholder | Rationale |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
-| `TB-ALGO-REPROCESS` | MVP | Token reprocessing semantics | `#tree-construction`, `#parsing-main-inbody` | `tree_builder/mod.rs`, `tree_builder/modes.rs` | Planned fixtures: `tb-reprocess-mode-switch`, `tb-reprocess-no-duplicate-patch`. | Reprocess current token after insertion-mode switch without losing token identity and without duplicate patch emission. | `tb-reprocess-core` | Required for spec-faithful mode transitions and deterministic emission. |
+| `TB-ALGO-REPROCESS` | MVP | Token reprocessing semantics | `#tree-construction`, `#parsing-main-inbody` | `tree_builder/dispatch/drive.rs`, `tree_builder/dispatch/template.rs`, `tree_builder/foreign/dispatch.rs` | AE13b4 dispatch, template/table, foreign-route, cycle, and whole/chunk tests. | Central same-token redispatch after insertion-mode switch; one-shot foreign HTML-rules route; internal delegation creates no attempt. | `tb-reprocess-core` | Required for spec-faithful mode transitions, deterministic emission, and authoritative production tracing. |
| `TB-ALGO-SOE` | MVP | Stack of open elements (SOE) | `#stack-of-open-elements` | `tree_builder/stack.rs`, `tree_builder/mod.rs` | Current proxy: `tree_builder/simple-element`. Planned fixtures: `tb-soe-nested-pop`, `tb-soe-implied-end-tags`. | Correct push/pop ordering, implied end tags, scope checks for end-tag processing. | `tb-soe-core` | Foundational invariant for all insertion modes. |
| `TB-ALGO-BODY-RECOVERY` | MVP_PARTIAL | Body-mode malformed-content recovery | `#parsing-main-inbody`, implied end tags | `tree_builder/body_recovery.rs`, `tree_builder/dispatch/in_body.rs`, `tree_builder/known_tags.rs` | Current fixtures: `ae7-*`, `f7-in-body-stray-end-tags`. | Paragraph auto-close, unmatched `` synthesis, list-item sibling recovery, supported implied end tags. | `tb-ae7-body-recovery` | AE7-supported subset only; not full `In body` conformance. |
| `TB-ALGO-AFE` | MVP_PARTIAL | Active formatting elements (AFE) | `#the-list-of-active-formatting-elements` | `tree_builder/formatting.rs`, `mod.rs` | Current fixtures: `h8-*`, `f13-*`; unit/session reconstruction tests. | Reconstruction triggers, marker boundaries, duplicate formatting entries. | `tb-afe-core` | Needed for supported in-body formatting fidelity; full formatting conformance remains out of scope. |
@@ -161,6 +167,11 @@ Explicitly deferred from Core v0 `In head`:
- No duplicate patch emission for the same semantic action during mode switches.
- Reprocessing must be implemented with the iterative dispatch loop above; recursion is not permitted in Core v0.
- Implementation should include a bounded reprocess-iteration guard in debug builds (for example, max 64 loop iterations per token) to catch infinite mode-flip bugs early.
+- AE13b4 observes one transition for each central attempt. Shared-template and
+ Text-mode handling are distinct paths; internal InBody/InHead/table
+ delegation is not a central attempt. Foreign breakout/end fallback returns
+ one `HtmlRulesOnly` redispatch, whose scope is included in exact cycle
+ identity. Template EOF unwind remains outside this trace boundary.
## SOE Ownership And Ordering Invariants (`TB-ALGO-SOE`)
@@ -206,6 +217,9 @@ Rationale:
supported static table parsing.
- The promoted scope remains declared and partial so Borrowser does not claim
full WHATWG table conformance.
+- AE13b4 exposes exact unsupported events for the missing same-named cell guard,
+ cell close preparation, and caption close preparation. It preserves AE8's
+ substitute tree/stack/AFE behavior and does not implement those algorithms.
## Core v0 Tree Builder Subset
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index e30418bd..fc95cf2d 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,4 +1,4 @@
[toolchain]
channel = "1.92.0"
profile = "minimal"
-components = ["rustfmt", "clippy"]
\ No newline at end of file
+components = ["rustfmt", "clippy", "rust-analyzer"]
\ No newline at end of file
|---|
|