Skip to content

Resolve property-table columns by header name (#132) + record B-0024 command↔prose join - #133

Merged
mobileskyfi merged 5 commits into
mainfrom
fix/132-property-table-columns
Jul 31, 2026
Merged

Resolve property-table columns by header name (#132) + record B-0024 command↔prose join#133
mobileskyfi merged 5 commits into
mainfrom
fix/132-property-table-columns

Conversation

@mobileskyfi

@mobileskyfi mobileskyfi commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Two commits: the #132 extraction fix, and the briefing that came out of triaging #131/#132 together.

Resolve property-table columns by header namecloses #132

parseProperties hardcoded description: row.cells[1], so any property table wider than two columns stored the wrong cell as the description.

Census of all 589 property/parameter tables in the vendored corpus (10 distinct header shapes):

Count Header shape Before
573 Property|Description, Parameter|Description correct
5 Property | Description | (ragged) correct
5 Property|Type|Default|Description 52 rows column-shifted
2 Property|Type|Description 70 rows yield nothing (name gate, #100)
1 Parameter|Description|Example correct
1 Feature / Property|Home|Basic|Advanced|ROSE 14 fabricated rows
1 Parameter|Value · 1 Menu|Parameter names|Page link yield nothing

| was only the most visible symptom. VETH has no entity in its Type cells, so address silently returned "IPv4/IPv6 address" instead of its prose — at high confidence, since /interface/veth/add is linked to that page.

The device-mode case was not in the issue as filed: a five-column feature matrix whose first header cell reads `Feature / Property` passed the old header regex and minted 14 rows that are not properties at all (`Containers` / type `/container` / description `"No"` — the Home column). #100's audit could not have caught it: that audit enumerated tables yielding zero properties, and this one yields garbage.

What changed: columns resolve by normalized header name — `Property`/`Parameter`, optional `Type`, optional `Default`, and a required `Description`. Requiring Description is what excludes the feature matrix and `| Parameter | Value |`; both already yielded garbage or nothing, so nothing real is lost. A dedicated Type/Default column wins over the parenthetical annotation in the name cell, falling back when empty. `|` is decoded once the cell is split — it's table syntax, not content; deliberately narrow, since general entity decoding would rewrite `"`/`<` corpus-wide.

The name gate is unchanged — that's #100's classification work. The ordering is load-bearing: the two `Property|Type|Description` tables hold 70 rows that yield nothing today because of that gate, so loosening it first would have ingested them with Type-as-description.

Blast radius — old vs new parser over the whole corpus: 4575 → 4561 rows, changes confined to exactly 3 files (device-mode 18→4, apps 45 corrected in place, veth 7 corrected in place). No collateral change anywhere else.

Apps' two `auto-update` records are retained and now differ — they only looked duplicated because the shift replaced both descriptions with the same Type cell. Not deduped.

Adds `apps.md`/`veth.md` as real fixtures; 22 new tests. Full suite 1066 pass / 0 fail; `make lint` green.

Record B-0024: the command↔prose join

Briefing only, no behavior change. Triage found #58, #61, and #131 are three symptoms of one defect: `commands.page_id` is the only join between the structure stores and the prose store, and it's a fuzzy, page-grained scalar.

The measurement that reframed it — `lookupProperty` confidence is miscalibrated in both directions:

Call Returns Confidence
`auto-update @ /app/add` column-shifted Type cell high
`address @ /interface/veth/add` column-shifted Type cell high
`vlan-ids @ /interface/bridge/vlan/add` correct prose + section anchor low

So #131's "prose is unreachable" framing is wrong (it's returned, just mislabeled and ranked under the corrupted Apps row — which this PR's first commit fixes), and linking bridge → page 27 would fix nothing (page 27 has zero properties; page 10 scores 0 unreachably).

Cross-links: B-0023 gains a second, correctness-driven consumer; B-0016 Q5 gains its first concrete consumer; B-0001/B-0011's `lookup_property` retirement is conditioned, not overturned — both fold targets sit on the wrong side of the broken join. Order: fix the join, recalibrate confidence, then decide the surface. BACKLOG index also gains B-0023, which was missing entirely.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved Markdown property-table parsing across varying column layouts.
    • Correctly handles optional Type and Default fields, escaped pipe characters, empty values, malformed rows, and duplicate-looking properties.
    • Excludes unrelated feature-matrix tables from property extraction.
  • Documentation

    • Added a new briefing covering command-to-prose linking improvements and updated related project briefings with status, sequencing, and follow-up details.
    • Documented the parsing fix in the unreleased changelog.

mobileskyfi and others added 2 commits July 31, 2026 10:46
Triage of #131/#132 measured `lookupProperty` directly for the first time and
found that #58, #61, and #131 are three symptoms of one structural defect:
`commands.page_id` is the only join between rosetta's structure stores
(`schema_nodes`/`commands`, `cliref_*`) and its prose store, and it is a
nullable scalar, page-grained, and fuzzy.

Key findings recorded in the new briefing:

- The bridge prose is NOT unreachable. The global fallback returns the correct
  page-10 `pvid` rows with correct section anchors, labeled `low` and ranked
  under a corrupted Apps row. The defect is the confidence label and ordering.
- Confidence is miscalibrated in both directions — `high` on column-shifted
  Apps/VETH rows, `low` on correct bridge rows.
- `scoreCandidate` simulation: page 10 scores 0 in every case and no
  segment-matching tweak reaches it, so "link bridge to page 10" is new
  machinery, not a scorer change. There is no override mechanism today.
- Census of all 589 property/parameter tables by header shape: 52 rows
  column-shifted (Apps, VETH) and 14 fabricated rows from a device-mode
  feature matrix. #100's audit enumerated zero-yield tables only, so a
  wrong-yield table was structurally invisible to it.
- #132 must land before #100, or 70 more rows ingest with the same column bug.

Cross-links added:

- B-0023 gains the join as a second, correctness-driven consumer of total
  section coverage (Option A / `_lead` decision unchanged).
- B-0016 Q5 gains its first concrete consumer — the overlay as a correctness
  input rather than advisory metadata.
- B-0001 and B-0011 gain a revisit trigger: the `lookup_property` retirement is
  conditioned, not overturned. Both fold targets sit on the wrong side of the
  broken join. Order: fix the join, recalibrate confidence, then decide the
  surface.
- BACKLOG briefings index gains B-0024, and B-0023 which was missing entirely.

No user-visible behavior change, so no CHANGELOG bullet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`parseProperties` hardcoded `description: row.cells[1]`, so any property table
wider than two columns stored the wrong cell as the description.

Measured against the vendored corpus (589 property/parameter tables, 10 distinct
header shapes — census in B-0024):

- 5 tables are `| Property | Type | Default | Description |` (Apps, VETH).
  52 rows stored their **Type** cell as the description with type/default_val
  left NULL. `&#124;` was only the most *visible* symptom: VETH has no entity
  in its Type cells, so `address` silently returned "IPv4/IPv6 address"
  instead of its prose — at `high` confidence, since /interface/veth/add is
  linked to that page.
- 1 table is a five-column `device-mode` feature matrix whose first header cell
  reads `**Feature / Property**`. It passed the old header regex and minted 14
  rows that are not properties at all (`Containers` / type `/container` /
  description `"No"` — the Home column).

Columns are now resolved by normalized header name: `Property`/`Parameter`,
optional `Type`, optional `Default`, and a required `Description`. Requiring an
explicit Description column is what excludes the feature matrix and
`| Parameter | Value |`; both already yielded garbage or nothing. A dedicated
Type/Default column wins over the parenthetical annotation in the name cell,
falling back when the cell is empty.

`&#124;` is decoded once the cell is split — it is table *syntax*, not content.
Deliberately narrow: general entity decoding would rewrite `&quot;`/`&lt;`
corpus-wide, which is out of scope, and `page_tables.raw_markdown` stays
byte-exact either way.

The bold-kebab **name** gate is unchanged — broadening what qualifies as a
property name is #100's classification work. That ordering matters: the two
`| Property | Type | Description |` tables in route-selection-and-filtering.md
hold 70 rows that yield nothing today because of that gate. Loosening it before
this fix would have ingested them with Type-as-description.

Corpus-wide diff of old vs new parser: 4575 -> 4561 rows, changes confined to
exactly 3 files (device-mode 18->4, apps 45 corrected in place, veth 7
corrected in place). No collateral change anywhere else.

Apps' two `auto-update` records are retained and now differ — they only looked
duplicated because the shift replaced both descriptions with the same Type cell.

Adds apps.md and veth.md as real fixtures; 22 new tests cover header-shape
resolution, both header spellings, the 3- and 4-column shapes, entity decoding,
empty-Type fallback, short rows, and the feature-matrix rejection.

Closes #132

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 31, 2026 17:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 91e96036-a7e1-42d4-8722-b8e43f4c2e93

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR updates parseProperties to support header-based Markdown property tables and adds tests for varied layouts. It also adds B-0024 and updates related briefing, backlog, changelog, and spelling records.

Changes

Property parsing and command-prose join

Layer / File(s) Summary
Header-based property parsing
src/extract-docusaurus.ts, src/extract-docusaurus.test.ts
Property columns are resolved by header names. Optional Type and Default columns are supported. Escaped pipes are decoded. Non-property tables and malformed rows are excluded. Tests cover real and synthetic table layouts.
Command-prose join design
briefings/B-0024-command-prose-join.md, briefings/B-0016-cli-reference-overlay-design.md, briefings/B-0023-page-section-normalization.md, briefings/B-0001-lookup-property-broad-fts.md, briefings/B-0011-tool-surface-review.md
B-0024 documents a corroborated, section-grained command-to-prose join. Related briefings record CLI-Reference integration and sequencing constraints.
Project status and release records
BACKLOG.md, CHANGELOG.md, project-words.txt
Project records describe the parser fix, briefing dependencies, B-0024 status, and new spelling entries.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: area:docusaurus

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies both main changes: header-based property-column parsing and the B-0024 command-to-prose join briefing.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/132-property-table-columns

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@briefings/B-0016-cli-reference-overlay-design.md`:
- Around line 330-338: The CLI-Reference crosswalk must use the complete join:
exact/alias resolution from cliref_entry_schema_links, source_path from
cliref_entries, and the computed field view cliref_field_inspect_links. Update
briefings/B-0016-cli-reference-overlay-design.md lines 330-338 to describe this
stored-entry-link-to-computed-field-view join, and update
briefings/B-0024-command-prose-join.md lines 112-124 to apply the same full join
in corroboration and rejection rules.

In `@briefings/B-0024-command-prose-join.md`:
- Around line 34-59: Update the `#132` measurement sections in this briefing,
including the repeated content around the later referenced range, so they are
explicitly marked as the pre-fix 2026-07-31 baseline or regenerated using the
header-based parseProperties() fix. Remove stale claims that parseProperties()
still hardcodes row.cells[1] and update the “Land `#132` first” future step to
reflect that the parser fix is already applied and documented in CHANGELOG.md.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 41ed2d67-4666-4f28-9ab5-feeabb572ee2

📥 Commits

Reviewing files that changed from the base of the PR and between 4cd7413 and ce25115.

⛔ Files ignored due to path filters (2)
  • fixtures/docusaurus/apps.md is excluded by !fixtures/**
  • fixtures/docusaurus/veth.md is excluded by !fixtures/**
📒 Files selected for processing (10)
  • BACKLOG.md
  • CHANGELOG.md
  • briefings/B-0001-lookup-property-broad-fts.md
  • briefings/B-0011-tool-surface-review.md
  • briefings/B-0016-cli-reference-overlay-design.md
  • briefings/B-0023-page-section-normalization.md
  • briefings/B-0024-command-prose-join.md
  • project-words.txt
  • src/extract-docusaurus.test.ts
  • src/extract-docusaurus.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
*

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Keep this Copilot instructions file short; put substantive rules in narrow instruction files under .github/instructions/*.instructions.md.

Files:

  • CHANGELOG.md
  • BACKLOG.md
  • project-words.txt
**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.md: Keep each project documentation file limited to its canonical role; prefer the documented canonical home instead of creating a new top-level Markdown file.
Do not duplicate content from this routing index; move operational detail, schema blocks, or long rule lists to their canonical documentation or instruction files.
Apply the repository's Markdown linting and fenced-code conventions, while excluding LLM instruction files where the repository explicitly requires that exclusion.

Files:

  • CHANGELOG.md
  • briefings/B-0024-command-prose-join.md
  • briefings/B-0011-tool-surface-review.md
  • BACKLOG.md
  • briefings/B-0023-page-section-normalization.md
  • briefings/B-0001-lookup-property-broad-fts.md
  • briefings/B-0016-cli-reference-overlay-design.md
CHANGELOG.md

📄 CodeRabbit inference engine (CLAUDE.md)

Record user-visible shipped changes in CHANGELOG.md under [Unreleased] or release sections.

Files:

  • CHANGELOG.md
**/*.{ts,tsx,md}

📄 CodeRabbit inference engine (AGENTS.md)

Keep the attribution boundary visible when community RouterOS skills surface, because they are supplemental rather than official MikroTik documentation.

Files:

  • CHANGELOG.md
  • briefings/B-0024-command-prose-join.md
  • briefings/B-0011-tool-surface-review.md
  • BACKLOG.md
  • briefings/B-0023-page-section-normalization.md
  • briefings/B-0001-lookup-property-broad-fts.md
  • src/extract-docusaurus.test.ts
  • src/extract-docusaurus.ts
  • briefings/B-0016-cli-reference-overlay-design.md
briefings/B-*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Store grounded research and decision support in briefings/B-*.md.

Files:

  • briefings/B-0024-command-prose-join.md
  • briefings/B-0011-tool-surface-review.md
  • briefings/B-0023-page-section-normalization.md
  • briefings/B-0001-lookup-property-broad-fts.md
  • briefings/B-0016-cli-reference-overlay-design.md
BACKLOG.md

📄 CodeRabbit inference engine (CLAUDE.md)

Put loose, unshaped thoughts in the BACKLOG.md Inbox and items waiting on a named external event in BACKLOG.md Triggers.

Files:

  • BACKLOG.md
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use Bun and TypeScript, including Bun-native runtime APIs such as bun:sqlite, Bun.serve, and bunx.

Rosetta uses Bun and TypeScript; prefer bun, bun test, and make verify where applicable, rather than Node/npm-oriented substitutes.

Files:

  • src/extract-docusaurus.test.ts
  • src/extract-docusaurus.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Rosetta is read-only documentation/schema context and must not connect to or modify a user's router.

Files:

  • src/extract-docusaurus.test.ts
  • src/extract-docusaurus.ts
🪛 LanguageTool
briefings/B-0024-command-prose-join.md

[grammar] ~23-~23: Ensure spelling is correct
Context: ...-07-31 triage of #131/#132 measured the join directly for the first time; that measu...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[style] ~156-~156: Consider using “who” when you are referring to a person instead of an object.
Context: ...ce. The corroborated join is a consumer that is not advisory metadata: it uses t...

(THAT_WHO)


[grammar] ~192-~192: Use a hyphen to join words.
Context: ...ay's behavior). - Cons: unproven end to end (cliref empty locally); cliref cover...

(QB_NEW_EN_HYPHEN)


[style] ~218-~218: Consider using a different verb for a more formal wording.
Context: ... narrowed to), but must not be sold as fixing the reported problem. ### D. Do nothin...

(FIX_RESOLVE)


[style] ~289-~289: ‘out of reach’ might be wordy. Consider a shorter alternative.
Context: ...#61's prose-only properties are still out of reach. Corroboration tells you `/ip/firewal...

(EN_WORDINESS_PREMIUM_OUT_OF_REACH)

briefings/B-0001-lookup-property-broad-fts.md

[style] ~86-~86: Try using more formal phrasing here.
Context: ...ted, exactly as the 2026-07-14 decision already said. Grounding and the proposed join fix: ...

(MENTIONED_PREVIOUSLY)

briefings/B-0016-cli-reference-overlay-design.md

[style] ~335-~335: Consider an alternative for the overused word “exactly”.
Context: ...command→field-name index**, which is exactly what that join lacks: `lookupProperty(n...

(EXACTLY_PRECISELY)

🔇 Additional comments (15)
src/extract-docusaurus.ts (2)

357-415: LGTM!


433-451: LGTM!

src/extract-docusaurus.test.ts (6)

37-37: LGTM!


53-54: LGTM!


233-289: LGTM!


291-328: LGTM!


330-351: LGTM!


353-388: LGTM!

briefings/B-0016-cli-reference-overlay-design.md (1)

10-13: LGTM!

briefings/B-0023-page-section-normalization.md (1)

5-7: LGTM!

Also applies to: 189-198

briefings/B-0001-lookup-property-broad-fts.md (1)

5-17: LGTM!

Also applies to: 60-89

briefings/B-0011-tool-surface-review.md (1)

5-7: LGTM!

Also applies to: 32-40

BACKLOG.md (1)

70-70: LGTM!

Also applies to: 80-93

CHANGELOG.md (1)

33-33: LGTM!

project-words.txt (1)

229-229: LGTM!

Also applies to: 231-231, 233-233, 237-237

Comment thread briefings/B-0016-cli-reference-overlay-design.md Outdated
Comment thread briefings/B-0024-command-prose-join.md Outdated
Parser (per Codex review on #132):

- `resolvePropertyColumns` now requires the name header to be *exactly*
  `property` or `parameter` after normalization, not merely to contain the word.
  The device-mode matrix was rejected only because it lacks a Description
  column; a two-column `| Feature / Property | Description |` would still have
  fabricated rows. The contract is now enforced by the code rather than by the
  corpus's present shape.
- `normalizeAnnotationCell` strips only *paired* emphasis delimiters, so an
  unpaired asterisk survives — a default of `*` (wildcard) or a type containing
  `a*b` was previously deleted. The corpus writes value syntax as several spans
  in one cell (`*yes* | *no*`), so an outer-wrapper-only rule would not work.

Both are behavior-neutral on the current corpus (old vs new parser over
manual/pages: 4561 -> 4561 rows, 0 files changed), which is the point — they
close holes the corpus does not happen to exercise. Three regression tests added.

B-0024 re-grounded (per Codex review on #131 + two CodeRabbit threads):

- **Blocker, confirmed empirically on v0.11.2-alpha.109:** CLI-Reference
  corroboration validates the *query*, not a *candidate row*. All four
  `properties` rows named `pvid` get the identical "field exists" answer, and no
  relational edge exists — `properties` has no entry_id/field_id/schema_node_id,
  and `cliref_entries.page_id` references `cliref_pages`, a different page store
  from `properties.page_id -> pages`. The claim that it could promote the bridge
  rows and reject the Apps row was wrong and is removed.
- **New Option A, grounded on the artifact:** section-grained menu-path
  extraction as the discriminating key. Sections `Port Settings` (147) and
  `Bridge Port Settings` (168) name `/interface/bridge/port` in their own text;
  Apps' `Properties` (666) names no bridge path. That is the row-level
  discrimination corroboration cannot provide. Explicitly marked a hypothesis
  pending a corpus-wide precision/recall pass, not a lean.
- CLI-Reference demoted to `(path, name)` validation only, with the complete
  two-hop crosswalk documented (stored entry link + computed field view) in both
  B-0024 and B-0016.
- Grounding switched to the CI artifact via `make db-sync`. Corrects two errors:
  the provenance table is `db_meta`, not `meta` (the repo-root DB was never
  unprovenanced), and `cliref_*` ships populated (228/1,051/10,118/931/13,036),
  so this was never future homework.
- #132 measurements relabeled as the pre-fix v0.11.1 baseline; "land #132 first"
  marked done in this PR.
- #131's reachability claim narrowed: the rows are unreachable through
  command-grounded lookup (accurate as filed) while remaining globally
  discoverable at `low`. The earlier "the framing is wrong" over-corrected.
- B-0023 corrected throughout: its lead-fragment work landed in PR #105, so
  B-0024 consumes total section coverage rather than raising its priority.

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

@mobileskyfi mobileskyfi left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex Review

Independent review at 6ddca0c. The #132 extractor change itself looks solid: an isolated rebuild from the vendored /docs cache produced 4,561 properties, no &#124; descriptions, 18→4 device-mode rows, correct Apps/VETH Type/Default/Description values, distinct properties/properties-1 anchors, source-row provenance, and clean SQLite integrity/FKs. Local validation is also green: 1,069 tests, focused extractor tests, typecheck, Biome, markdownlint, and cspell.

The remaining blockers are documentation/design-state corrections in the inline comments. One additional linked-issue loose end: #132's acceptance bullet currently says device-mode.md contributes zero property rows, but the correct rebuild retains four legitimate rows and removes only the 14 fabricated feature-matrix rows (the PR body correctly says 18→4). Please amend that acceptance bullet to say the feature matrix contributes zero rows so Closes #132 does not leave an apparently unmet criterion.

Comment thread briefings/B-0024-command-prose-join.md Outdated
Comment thread briefings/B-0016-cli-reference-overlay-design.md
Comment thread briefings/B-0023-page-section-normalization.md
… text

Codex review at 6ddca0c. All four findings valid.

**Option A was overstated, and the omission was mine.** The section-grained
key was presented as "current lean" with a table listing only the convenient
paths. The same artifact I cited already shows it is coarser than that:

- `/ip/settings` appears in section 140's text and *passes* `isRouterOsPath()`
  (`ip` is a top-level menu, src/link-commands.ts:82). I dropped it from the
  table. The doc-slug filter catches relative links; it does not catch a
  genuine but unrelated menu mention.
- Section 140 is shared by **49** property rows, all inheriting that path set.
  A fragment-level signal was being presented as a row-level key.

The option table now lists every path with its isRouterOsPath verdict struck
through or not, records rows-sharing-fragment counts, and is relabeled
**hypothesis, not yet a lean**. Step 3 now explicitly measures granularity
(properties-per-fragment, paths-per-fragment, unrelated-path rate) alongside
accuracy, and names the nearer candidate key Codex points at:
`properties.source_table_row_id` -> `page_tables`, which is strictly finer than
the section. If coarseness dominates, Option A is a ranking signal, not a key.

"current lean" wording corrected in B-0023 and BACKLOG so downstream
implementation does not treat the direction as settled.

**B-0016 lifecycle text was stale.** It still said #124 was "cleared to
implement" and named "#124 landing" as the next trigger. #124 is closed and the
overlay shipped via #126/#128. Now records the landed/validated ETL with the
shipped counts and leaves the briefing open only for Q3/Q5/Q7/Q8.

**B-0023 carried a completed prerequisite as open.** Its decision was
implemented in #105 and it ends with "Open questions: None blocking
implementation", so per the briefings lifecycle it is now `status: resolved`
with a dated resolution note, and the BACKLOG index matches.

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

Copy link
Copy Markdown
Contributor Author

Codex review at 6ddca0c — all four items addressed in 885f34c

Thanks, all four were valid. The first one was a presentation error on my part, not just an overstatement.

1. Option A relabeled a hypothesis; the coarseness is now shown, not hidden

You're right, and the omission was mine: /ip/settings is in section 140's text, it does pass isRouterOsPath() (ip is a top-level menu, src/link-commands.ts:82), and I left it out of the table while quoting the same query that produced it. Section 140 is also shared by 49 property rows, so a fragment-level signal was being presented as a row-level key.

The table now lists every path with its filter verdict (struck through = rejected) and a rows-sharing-fragment column:

Section Page Rows sharing it Paths in its own text
Port Settings (147) 10 26 /interface/bridge/port/set, /interface/bridge/port, /virtual-private-networks/eoip
Bridge Port Settings (168) 10 4 /interface/bridge/port
Bridge Interface Setup (140) 10 49 /interface/bridge, /interface/bridge/host, /ip/settings, /firewall-and-quality-of-service/packet-flow-in-routeros
Properties (666) 38 Apps /authentication-authorization-accounting/certificates

Heading is now "hypothesis, not yet a lean", and step 3 measures granularity (properties-per-fragment, paths-per-fragment, unrelated-path rate) alongside accuracy — with the explicit out that if coarseness dominates, Option A is a ranking signal rather than a key.

I also took your "nearer row/table-to-sub-menu key" hint concretely: properties.source_table_row_idpage_table_rowspage_tables gives each property its own table with its own source_heading, strictly finer than the section (140's 49 rows span more than one table). Named as a co-equal candidate to measure, not an assumption.

"current lean" wording corrected in B-0023 and BACKLOG too.

2. B-0016 lifecycle text updated

Replaced the stale "cleared to implement" / "stays open until #124's extractor lands" / "next trigger: #124 landing" text with the landed-and-validated state (#124 closed, shipped via #126/#128, with the v0.11.2-alpha.109 counts and the two CI gates). Q1/Q2/Q4/Q6/Q9/Q10 marked settled and implemented; the briefing stays open only for Q3, Q5, Q7, Q8, with the next trigger now an answer to Q3 on #25.

3. B-0023 closed out

Right — it ends with "None blocking implementation" and its work landed in #105, so carrying it as open contradicted the briefings lifecycle. Now status: resolved with a dated note pointing the follow-on join work at B-0024, and the BACKLOG index matches.

4. #132 acceptance bullet corrected

Posted as a correction on the issue: my bullet said "device-mode.md contributes zero property rows", which is wrong — only the feature matrix contributes zero. The page's real List of available properties table keeps its four legitimate rows (activation-timeout, flagging-enabled, flagged, advanced), so 18 → 4 as the PR body says. Closes #132 no longer has an unmet criterion.

Suite 1069 pass / 0 fail; make lint green.

@mobileskyfi mobileskyfi left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up review at 885f34c: two original threads are fully addressed and resolved. The B-0024 design thread remains open because the proposed table-grained correction does not match the cited artifact. One additional stale cross-reference is inline below.

Comment thread briefings/B-0016-cli-reference-overlay-design.md Outdated
Codex re-review at 885f34c. Both findings valid and verified on
v0.11.2-alpha.109.

**The table-grained "nearer key" was wrong.** I claimed section 140's 49 rows
span more than one table. They do not: all 49 point into a single page_tables
row (id 70, 49 data rows, zero properties lacking source_table_row_id). Its
source_heading is the bare text "Bridge Interface Setup" with no path, and the
paths inside its own raw_markdown are the *same set* the section yields —
/interface/bridge x2, /interface/bridge/host, and /ip/settings. So table
granularity collapses onto section granularity here and cannot improve the
example at all; the finding is slightly stronger than the review stated.

Reframed as what would actually help: a nearest-preceding-menu-path
(proximity) join. The /interface/bridge submenu context precedes the table in
source order, so the discriminating signal is proximity to the property's own
row — which needs source-position provenance the schema does not carry today.
Recorded as a candidate requiring new provenance, not an existing key to switch
to. Step 3 now measures tables-per-section distribution (before assuming a finer
structural fragment exists) and proximity-join feasibility.

Also corrected: Apps section 666 has 14 properties, not "—".

**The demotion had not propagated.** B-0016 still called fragment alignment
"B-0024's discriminating key"; B-0023 (note + cross-reference) and the BACKLOG
B-0023 row still said "section→command join", which reads as settled. All now
describe the open work as the command↔prose join evaluating fragment/proximity
signals, with section granularity explicitly not established as its key.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mobileskyfi
mobileskyfi merged commit 9557945 into main Jul 31, 2026
9 of 10 checks passed
@mobileskyfi
mobileskyfi deleted the fix/132-property-table-columns branch July 31, 2026 21:41
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.

Apps page property extraction: value-syntax strings with literal HTML entities stored as descriptions (*yes* &#124; *no*), duplicated rows

2 participants