Skip to content

S529 A2 — "Guides are concepts" vs B.1/B.2: which requirement is live, and what are guides built on?

Task: id-417 D1, lane A2. Session: S529. Posture: read-only on code; requirement-first.

Headline. The two sources are not in conflict at the requirement level. B.1 and B.2 are requirements about presentation and vocabulary/completeness; “guides are concepts” is a claim about substrate. Both hold, and the reconciliation the dispatch offered — concept-clusters as substrate, B.1’s nesting as the presentation rule — survives challenge. The genuine collision is narrower than either framing suggests and is not about primary_domain/primary_subtopic: it is about who authors a cluster’s structure (human curation vs producer derivation) and where the rows live (Platform DB vs client-owned bundle repo). Neither ratified source settles that, so it is carried as UNDECIDABLE.

Two premises in the dispatch brief were measured false and are corrected in §4 and §5.


Source: kh-client-content-archive/docs/client-briefs/kb-hub-gap-analysis-action-tracker.md, opened 22/04/2026 (line 18: “Date opened: 22/04/2026 (S189 close-out)”).

Applying the owner’s binding directive — “it’s not the approach outlined in the docs that’s important, but the underlying requirement that needs to be implemented” — each item splits into a Liam decision (the requirement) and a Next action (spec) (the disposable design).

B.1 — the requirement is progressive disclosure, and it is anti-filter

Section titled “B.1 — the requirement is progressive disclosure, and it is anti-filter”

Tracker lines 39-44, the recorded decision:

Status: 🔵 Spec pending. Liam decision: Option (ii). Layer becomes a UI nesting rule: each topic section displays Sales Brief at the top and Bid Detail nested beneath, programmatically. Context: currently layers are metadata tags used for filtering, not for UI hierarchy. Advanced Audits §13 “Security & Compliance” is one section at bid_detail layer; mind-map intent was Security (Sales Brief) with Security (Bid Detail) nested.

Underlying requirement: within one topic, a reader gets the audience-appropriate depth first, with detail available beneath rather than elsewhere. Sales Brief and Bid Detail for the same topic must be co-present and ordered, not split into sibling sections a reader has to hunt between.

Two things follow that the census framing missed:

  1. B.1 is not a taxonomy requirement. It says nothing about subject classification. It is entirely about ordering material already known to belong to one topic.
  2. B.1 explicitly asks for layer to stop being a filter. The words “currently layers are metadata tags used for filtering, not for UI hierarchy” are the complaint, not the spec. Any reading that treats B.1 as evidence for retaining filter columns inverts it.

The design B.1 proposes — and which is disposable — is tracker lines 46-58: parent_section_id or a new layer_priority_order column, get_guide_content returning layer-grouped buckets, a zero-row migration.

Checked as the dispatch asked — does the code implement B.1’s layer as a filter? Historically yes, today no (§4). expected_layer is now returned by get_guide_content as inert passthrough and is used in exactly one live place as a presentation discriminator, not a filter:

app/guide/[slug]/guide-content.tsx:273-275

// Detect if a section is the research feed (expected_layer = 'research')
… section.expected_layer === 'research';

That is a small, real instance of B.1’s own pattern (layer driving rendering, not filtering), shipped for the Research Feed via B.6.

B.2 — the requirement is client-recognisable vocabulary + completeness

Section titled “B.2 — the requirement is client-recognisable vocabulary + completeness”

Tracker lines 64-67, the recorded decision:

Status: 🔵 Spec pending. Liam decision: Align naming to mind map for ALL sections + add ALL missing sections. This also covers §7.4 (sector↔product cross-refs) and some of §7.7.

The body is a rename table (lines 69-82: “Elevator Pitch” → “Product Overview”; “Differentiators” → “The Value Proposition”; …) and an additions list (lines 84-94: “Problems It Solves”, “Relevant Sectors”, “ROI & Impact Evidence”, “IMPACT of ‘If Not Now’”, “Functionality (capability matrix)”, “External Parties”, “FAQs”), with line 96-99 setting the shape: “LMS / Websites / Advanced Audits share 19-section structure today. After changes expect 24-26 sections per Product Guide.”

Underlying requirement: a product’s guide must present the client’s own mental model of their product story — their names, their full set of topics — and must make an unfilled topic visible rather than absent. That last clause is the is_required semantics: a named-but-empty section is the gap signal.

Critically, the classification columns appear only in B.2’s design, never in its decision. The sole mention is tracker line 105-107, inside “Next action (spec + migration)”:

  • New-section INSERT list (section_name, expected_layer, display_order, subtopic_filter, content_type_filter).
  • Impact on existing subtopic_filter wiring (S189 WP4 populated 14 subtopics across the 19 existing sections — reassess for the 24-26 new layout).

Under the owner directive this is exactly the layer to strip. B.1 and B.2 do not require primary_domain/primary_subtopic at the requirement level. They require a membership predicate — some way to decide what belongs in a named cluster — and the tracker’s proposal happened to reach for the taxonomy columns that existed in April 2026. The census treating B.1/B.2 as the surviving requirement-backed consumer of those columns read the design as the requirement.

B.4 / B.5 / B.6 (owner-named, read for context)

Section titled “B.4 / B.5 / B.6 (owner-named, read for context)”
  • B.4 (lines 150-182) — Standard/Advanced tiering at guide-section level; recommends option (i) parent_section_id, noting it “composes naturally with B.1 (layer nesting within each tier)”. Same shape as B.1: a hierarchy/presentation requirement, not a taxonomy one. Line 154-156 records the answer-level version as already solved.
  • B.5 (lines 184-233) — recurring-review cadence (next_review_date, review_cadence_days). This is the freshness axis, not the guides axis; it lands on content_items (now dropped) and is the tracker’s contribution to what record_lifecycle later formalised. No guides bearing.
  • B.6 (lines 235-241) — 🟢 Shipped S189 WP5, the only closed item in Section B. Evidence line 237-240: migration 20260422174117_add_research_feed_to_product_guides.sql, three guides gain section_name='Research Feed', expected_layer='research', display_order=20. This is the live proof that expected_layer is usable as a rendering discriminator (§1, B.1 above) — B.6 is B.1’s requirement shipped in miniature, for one section.

Client feedback (kh-client-feedback.md, 29/04/2026) — read in full, 38 lines

Section titled “Client feedback (kh-client-feedback.md, 29/04/2026) — read in full, 38 lines”

Two items bear on guides, and they pull against retiring the subject axis:

  • Item 2 (line 23, final cause): “when I tried domain-filtering to security it returned good content but excluded product-feature and implementation entries which is where a lot of the LMS-specific answers live; either the filter logic needs to be more permissive or the ingest needs to apply secondary tags so security-adjacent product content is reachable from a security search.” This asks for the subject axis to become multi-valued, i.e. more subject reach — it is not a complaint that subject classification exists.
  • Item 3 (line 33) is a safety requirement on a different axis entirely: “A high-confidence match in the wrong scope is much more dangerous than a low-confidence match in the right scope.” Scope (internal-it / production-infrastructure / office-physical / data-centre-physical) is orthogonal to subject — the Bitdefender example is correctly subject-classified and wrongly scoped. scope_tag therefore adds an axis; it does not substitute for one.

2. What “guides are concepts” actually claims

Section titled “2. What “guides are concepts” actually claims”

Source: initiatives/core-product/knowledge-base-foundations/okf-platform/corpus-reframe-review.html. Quoted in full from the prose body (recovered by stripping tags; also filed verbatim in mempalace, wing wing_canonical, room initiatives):

And yes — Guides are concepts. Product/service guides are curated concept-clusters, and the existing “coverage” idea (what the corpus can fill vs. where the gaps are) is the enrichment/discovery loop wearing product clothes. Gap-surfacing is arguably the strongest week-1 deliverable for a typical SMB: connect messy sources, show them what their data can’t yet answer.

Date. Git: 2026-07-24 a99162a3 chore: update documentation (only commit touching the file). That is ~3 months after the tracker opened (22/04/2026) and ~3 months after the client feedback (29/04/2026). Recency favours the reframe. Per the dispatch, recency alone does not settle it — and in the event it does not need to, because §3 finds no requirement-level conflict.

Scope — and this is a qualification the dispatch framing did not carry. The passage is prose; its ratified expression is R8, and R8’s effect line is the weakest in the R1-R8 set:

R8 — Connector-first register + the growth story. … “Roadmap theme 15 explicitly gains: cocoindex connectors, the OKF discovery agent, the PDF-library quick win, and **guides-as-concepts

  • coverage/gap-surfacing as the week-1 value path**.” effect: ‘ID-138 TECH must-encode · roadmap theme 15 update’

Compare R1 (“Amends DR-023 wording · rewrites deployment-architecture §3”), R2 (“Restates DR-020”), R3 (“Amends DR-024(ii)”), R5 (“BI-amendment to id-132”). Those amend decision records and architecture docs. Guides-as-concepts is ratified as a roadmap theme placement — the “guides-as-concepts” clause sits in the roadmap half of R8, not in the ID-138 TECH must-encode half (which is the connector-first register).

So the honest reading: “guides are concepts” is a ratified statement of product direction, not a ratified schema ruling. It has enough authority to say guides belong on the concept path; it does not carry authority to void a DB design on its own. Two further observations:

  1. It promotes the coverage idea rather than retiring it — “the strongest week-1 deliverable”. Any inference from this passage to “coverage is dead” runs backwards. (DR-034 retired the content_items-era coverage feature; R8 re-founds the requirement on a new substrate.)
  2. It is scoped to “Product/service guides” by its own words — it does not name sector guides or the generated intelligence guides (lib/intelligence/intelligence-guide-generator.ts:95-98, which writes expected_layer: 'research' + content_type_filter: 'article'). Carried as UNDECIDABLE-4.

No, not at the requirement level — and the evidence that they compose is stronger than the evidence that they collide. Showing the work in both directions.

(a) The layers are different. B.1 = presentation ordering. B.2 = vocabulary + completeness. “Guides are concepts” = what the cluster is made of. A concept-cluster with an ordering rule over its members satisfies B.1; a concept-cluster whose members are named to the client’s mind map and whose empty slots are visible satisfies B.2. Nothing in the concept model forbids either.

(b) Guide types already are concept types. Measured — the closed client-business concept set, scripts/cocoindex_pipeline/producer/validator.py:116-118:

ALLOWED_CONCEPT_TYPES = frozenset(
{"topic", "product", "company", "certification", "case_study"}
)

against guides.guide_type ∈ ('sector','product','company','research','custom') (live DB, §4). The intersection is {product, company} outright, with sectortopic. A “Product Guide” is already, by type, a product concept. That is a strong structural corroboration of the reframe and it costs B.1/B.2 nothing.

(c) B.2’s is_required is gap-surfacing. B.2 wants named sections that may be empty; R8 wants “show them what their data can’t yet answer”. These are the same mechanism described from the product end and the value end. B.2 is not a rival to gap-surfacing — it is the client-specific instance of it.

(d) The coverage requirement is live on both sides. DR-034 retired an implementation; R8 promotes the requirement to week-1. Neither source retires gap-surfacing.

Evidence they collide — and where the collision actually is

Section titled “Evidence they collide — and where the collision actually is”

The collision is not primary_domain/primary_subtopic (B.1/B.2 do not require them, §1). It is two structural facts about the concept layer, both measured:

(i) Concepts are not database rows. Live Platform staging (rbwqewalexrzgxtvcqrh):

SELECT table_name FROM information_schema.tables
WHERE table_schema='public' AND (table_name ILIKE '%concept%' OR table_name ILIKE '%guide%'
OR table_name ILIKE '%bundle%') ORDER BY 1;
guide_sections | guides | product_guide_workspaces

No concepts table exists. Concepts are typed markdown files in a client-owned git repo (bundle-doctrine.md §“Bundle taxonomy”: class Client business, repo canonical-okf-bundle-cN, Owner: Client (DR-016); §“Composition”: “Repo = ownership unit · bundle = knowledge-scope unit”). B.1 and B.2 are, mechanically, migrations against guide_sections in the Platform DB (B.2 line 98-99: “Migration = one guide_sections INSERT/UPDATE migration × 3 guides (57→72-78 rows)”). If guides become concepts, B.1/B.2’s migrations are void while their requirements survive — restated as bundle-shape requirements: concept ordering/nesting (B.1), cluster vocabulary + visible-gap completeness (B.2).

(ii) Curated vs derived. bundle-doctrine.md §“Two production paths”:

Path 1 — refinery-gated. Client BUSINESS knowledge: evidence → cocoindex sieve → staged proposals → human promotion gate → canonical L-records → id-132 producer → bundle.

Client-business concepts are producer output derived from promoted L-records. B.2’s decision is “align naming to mind map for ALL sections + add ALL missing sections” — a human curating a structure the corpus does not yet contain, including sections deliberately created empty. The reframe’s own word is “curated concept-clusters”, which does not obviously sit on Path 1 and has no named Path.

This is the real conflict, and it is a single question: does a guide’s cluster structure get authored by a human against the client’s mind map, or derived by the producer from what was promoted? Both sources are silent. Carried as UNDECIDABLE-1.

Both requirements are live. B.1 and B.2 are live requirements about how a guide presents and what it is called; “guides are concepts” is a live statement about what a guide is made of. The dispatch’s proposed reconciliation holds: concept-clusters as substrate, B.1’s nesting as the presentation rule, B.2’s mind-map vocabulary as the cluster’s naming and completeness contract. No winner is needed, and forcing one would discard a requirement in either direction.

What genuinely is superseded is neither document’s requirement but the April-2026 design that B.1/B.2 proposed — because the table it targeted (content_items) no longer exists (§4).


Two premises in the dispatch brief are false as stated. The brief says get_guide_content and get_guide_coverage are “both still LEFT JOIN content_items”. Neither is.

Command 1 — do the functions exist, and what do they reference?

SELECT n.nspname, p.proname, pg_get_functiondef(p.oid) FROM pg_proc p
JOIN pg_namespace n ON n.oid=p.pronamespace WHERE p.proname LIKE 'get_guide%' ORDER BY 1,2;

Result: two rows onlyapi.get_guide_content (thin wrapper) and public.get_guide_content. get_guide_coverage returned zero rows: it does not exist in any schema. It was retired at id-131 (20260706104000_id131_coverage_retire.sql) under DR-034’s ruling that the content_items-era coverage feature “is RETIRED, not re-pointed”.

public.get_guide_content body, verbatim from the live DB:

SELECT gs.id AS section_id, gs.section_name, gs.description AS section_description,
gs.display_order AS section_order, gs.expected_layer, gs.subtopic_filter, gs.is_required,
-- content_items (the sole source of per-item content matching) was dropped at M6
-- … Every content_* column is explicitly NULL until a product/schema decision
-- restores (or formally retires) guide content matching.
NULL::"uuid" AS content_id, NULL::"text" AS content_title, NULL::"text" AS content_type,
NULL::"text" AS content_layer, NULL::"text" AS content_brief, NULL::"text" AS content_freshness,
NULL::timestamp with time zone AS content_verified_at,
NULL::timestamp with time zone AS content_captured_date
FROM guide_sections gs JOIN guides g ON g.id = gs.guide_id
WHERE g.slug = p_guide_slug ORDER BY gs.display_order;

The only content_items occurrence is in a comment. The join was stripped at supabase/migrations/20260707210000_fix_get_guide_content_content_items_residue.sql (S451), whose header documents the fix and the reason: the layer axis “has NO successor column on source_documents or q_a_pairs (verified live)”.

Consequence for the S528 round-1 board: ruling A3“Reproduce and fix the get_guide_content / get_guide_coverage content_items join now — is already satisfied and is largely a no-op: get_guide_content was fixed at S451, three weeks before S528, and get_guide_coverage was retired at id-131. A3 should be closed as done-on-arrival rather than executed.

Command 2 — end-to-end probe over every real guide:

SELECT g.slug, g.guide_type, g.domain_filter,
(SELECT count(*) FROM public.get_guide_content(g.slug)) AS rows_returned,
(SELECT count(*) FROM public.get_guide_content(g.slug) x WHERE x.content_id IS NOT NULL) AS rows_with_content
FROM public.guides g ORDER BY g.slug;
slugguide_typedomain_filterrows_returnedrows_with_content
ci-test-guidesectornull30
mcp-eval-guidecustomsecurity30
mcp-eval-guide-1785438527030customnull30
mcp-eval-protocol-testcustomnull00

Command 3 — corpus shape:

SELECT to_regclass('public.content_items') AS content_items_tbl,
(SELECT count(*) FROM public.guides) AS guides_n,
(SELECT count(*) FROM public.guide_sections) AS sections_n,
(SELECT count(*) FROM public.guide_sections WHERE expected_layer IS NOT NULL) AS with_layer,
(SELECT count(*) FROM public.guide_sections WHERE subtopic_filter IS NOT NULL) AS with_subtopic,
(SELECT count(*) FROM public.guide_sections WHERE content_type_filter IS NOT NULL) AS with_ctype,
(SELECT count(*) FROM public.guides WHERE domain_filter IS NOT NULL) AS guides_with_domain_filter,
(SELECT count(*) FROM public.guide_sections WHERE parent_section_id IS NOT NULL) AS nested_sections;
content_items_tbl: null | guides_n: 4 | sections_n: 9 | with_layer: 3 | with_subtopic: 3
with_ctype: 3 | guides_with_domain_filter: 1 | nested_sections: 0

Answer: guides render, and are structurally empty. The page loads (sections, ordering, TOC); every section takes the GuideSectionEmpty path. app/api/guides/[slug]/route.ts:112-114 still carries the comment “Only add content items if there is one (LEFT JOIN may produce NULLs)” — that branch is now never taken.

Two further measured facts, stated not as retire evidence (population is not evidence — owner ruling S528) but because they bound what any verdict can rely on:

  • nested_sections: 0 — B.1’s proposed Phase-1 mechanism (parent_section_id) and B.4’s recommended option (i) are both unexercised; no data has ever been shaped that way.
  • sections_n: 9 across 4 guides, all ci-test/mcp-eval slugs. The 57→60-row client Product Guide corpus B.2 describes is not in the Platform DB — consistent with Platform data being synthetic pre-launch. B.1/B.2’s subject matter lives in client projects, not here.

5. What guides need instead of primary_domain/primary_subtopic

Section titled “5. What guides need instead of primary_domain/primary_subtopic”

Measured: get_guide_content does not reference primary_domain or primary_subtopic at all, and never did — it reached them through content_items. Post-M6 it reads neither. expected_layer and subtopic_filter are returned as inert passthrough projection (echoed to the client, used in no predicate); content_type_filter is not even projected; guides.domain_filter is not referenced by the RPC.

The one place the requirement is implemented is orphaned

Section titled “The one place the requirement is implemented is orphaned”

lib/guide-section-mapping.ts::suggestGuideSections is the only code that uses all four columns as matching predicateslib/guide-section-mapping.ts:123-126:

.select('id, section_name, subtopic_filter, expected_layer, content_type_filter, display_order,
is_required, guides!inner(id, name, slug, domain_filter, display_order, is_published)')
.eq('guides.is_published', true)
.in('guides.domain_filter', matchDomains);

Its docstring (lib/guide-section-mapping.ts:79-81) states the requirement exactly:

Suggest guide sections that a content item would populate based on its classification metadata.

That is R8’s gap-surfacing loop, in code. Measured: its only importers are two test files (__tests__/lib/guide-section-mapping.test.ts:6, __tests__/lib/guides/product-guide-resolution.test.ts:24) — no production caller. And measured:

bun run test -- __tests__/lib/guide-section-mapping.test.ts __tests__/lib/guides/product-guide-resolution.test.ts
→ Test Files 2 passed (2) · Tests 74 passed (74) · Duration 689ms

74 green tests guarding a function nothing calls. Per the dispatch, consumer-counting and grep absence are not evidence — so this is not offered as a retire argument. It is offered as the opposite: the requirement R8 calls the week-1 deliverable has a working, fully-tested implementation that is simply not wired to anything, and 74 tests that will stay green whatever is decided about the columns. That is precisely id-417’s titled failure mode (“the tests that encode them”) and it means test-suite health carries no signal on this question.

What guides actually need: a membership predicate

Section titled “What guides actually need: a membership predicate”

Stripped to requirement, all four columns serve one job: decide whether a record belongs in a named cluster. That job is live — B.2 needs it to fill sections, R8 needs it to surface gaps. What is not required is that the predicate be primary_domain/primary_subtopic specifically.

Candidate substrates available today, measured live:

GrainSubject axis availableLayer axis
source_documentsprimary_domain, primary_subtopic, secondary_domain, secondary_subtopicnone (eliminated at M6)
q_a_pairsrecord_lifecycle.domain only (no subtopic)none
reference_itemsprimary_domain, primary_subtopiclayer exists and is live
all grains (planned)id-162 cross-grain keyword arrays

Two consequences for B.1 specifically:

  • B.1’s nesting requirement currently has no data to nest on the document/answer grain. The S451 fix-migration header records this and I verified the shape live: layer survives only on reference_items. B.1 is a live requirement with an absent substrate (UNDECIDABLE-3).
  • A partial re-point onto reference_items.layer (e.g. research-layer sections) was flagged but never evaluated — that migration header says so explicitly and calls it “out of this fix’s authority”.

And one consequence for Item 2: suggestGuideSections is the only implementation of the client’s secondary-tag reach requirement — lib/guide-section-mapping.ts:195-196 matches when guide.domain_filter === secondaryDomain. hybrid_search filters on primary only (§below). Deleting the guides mapping code would remove the sole implementation of client Item 2.

Testing the id-417 search-chain claim — the claim is false as stated

Section titled “Testing the id-417 search-chain claim — the claim is false as stated”

id-417 argues: “domain/subtopic filtering in search is what those replace — not something to preserve”, citing id-144 / id-162 / id-135. Verified against the live function, not assumed.

public.hybrid_search signature (live):

hybrid_search(query_embedding vector, query_text text, similarity_threshold numeric,
limit_count integer, include_superseded boolean, visibility_filter varchar, application_type text,
filter_kind text, filter_domain text, filter_subtopic text,
filter_date_from timestamptz, filter_date_to timestamptz)

filter_domain and filter_subtopic are live predicates on every arm, e.g. arms 1 and 2:

AND (filter_domain IS NULL OR sd.primary_domain::text = filter_domain)
AND (filter_subtopic IS NULL OR sd.primary_subtopic::text = filter_subtopic)

and arm 4 the same on ri.*; arm 3 uses COALESCE(rl.domain,'unclassified'). Decisively, id-144 is the migration that added them — its own in-body comment on arm 1:

-- filter_kind/domain/subtopic/date guards (§2.4) added; scope_tag/source_url are NULL for this grain (§2.1).

So id-144 carried the subject axis forward and added scope_tag alongside it (arm 3 projects qa.scope_tag, per -- id-144: projects qa.scope_tag (§2.1, the Item-3 safety projection)). scope_tag is an orthogonal safety axis (client Item 3), not a substitute for the subject axis (client Item 2 asks for more subject reach). And id-162 is explicitly additivetasks/id-162.md:14: “The new keyword filter axis is the FIRST to hit the DR-052 positional-param cap: it MUST arrive as a strictly-validated jsonb filters arg … never a 13th positional arg” — a 13th filter alongside the existing 12, which necessarily keeps filter_domain/filter_subtopic.

Verdict: id-144/id-162/id-135 extend the filter surface; they do not replace the subject axis. The id-417 passage that reverses round 1 on this point is itself wrong on this point. (Its conclusion — that search/browse filters shouldn’t carry a KEEP verdict by consumer-counting — may still stand on other grounds; but not on “those replace it”.)

Corroborating A7 concretely. The subtopic defect A7 folds into taxonomy work is visible in arm 3:

AND (filter_subtopic IS NULL OR NULL::text = filter_subtopic)

NULL::text = <anything> is never true, so any non-null filter_subtopic silently excludes every q_a_pair — the answer grain vanishes from subtopic-filtered search. That is exactly the client’s Item-2 experience (“no relevant content” on questions the corpus answers), and it is a bug in the predicate, not evidence that the axis is unwanted.

  1. A membership predicate over a multi-valued subject axis — B.2’s sections must fill, and client Item 2 requires secondary reach. Whether that predicate is the current taxonomy columns, the ontology CV, or id-162’s keyword arrays is a substrate choice this lane does not decide.
  2. An ordering/nesting rule over cluster members — B.1, B.4. This needs a per-record audience axis; the one it was designed against no longer exists on the document/answer grain.
  3. A named-but-empty cluster slot — B.2’s is_required, which is R8’s gap-surfacing mechanism.
  4. Nothing that requires the predicate to be primary_domain/primary_subtopic specifically.

Implication for the census, stated as implication and not verdict: guides/guide_sections is not a requirement-backed consumer of primary_domain/primary_subtopic. It is a requirement-backed consumer of a membership predicate, whose April-2026 design happened to name those columns. The census’s last anchor does not hold in the form the census stated it — but the requirement underneath it is live, and load-bearing for the week-1 value path. No retire verdict is given here, and D1 still needs the ingest-model answer (lane A1) before one is possible.


Questions carried verbatim.

UNDECIDABLE-1 — the real conflict. “Who authors a guide’s cluster structure — a human curating to the client’s mind map (B.2’s ‘align naming to mind map for ALL sections + add ALL missing sections’), or the id-132 producer deriving it from promoted L-records (bundle-doctrine Path 1)?” Neither source rules. B.2 requires human-curated structure including deliberately-empty sections; Path 1 derives concepts from what was promoted. “Curated concept-clusters” names the tension without resolving it.

UNDECIDABLE-2 — the storage home. “If guides become concepts in the client-owned bundle repo (canonical-okf-bundle-cN, Owner: Client, DR-016), do guides/guide_sections remain Platform DB tables, or become a producer projection into the bundle?” bundle-doctrine.md names four bundle classes and no guide class; the concept type set {topic, product, company, certification, case_study} contains no guide type, though product and company overlap guide_type outright.

UNDECIDABLE-3 — B.1’s absent substrate. “Does B.1’s layer-nesting requirement survive when no document or answer grain carries layer, and is the flagged-but-never-evaluated partial re-point onto reference_items.layer viable?” Requirement is live and ratified; the data axis it was specified against was eliminated at M6. The S451 migration header explicitly leaves this open and out of its authority.

UNDECIDABLE-4 — scope of the reframe. “Is ‘guides are concepts’ scoped to Product/service guides only (its own words), or does it also cover sector guides and the generated intelligence guides (lib/intelligence/intelligence-guide-generator.ts)?” The passage says “Product/service guides”. Three of four live guides are guide_type='custom'.

UNDECIDABLE-5 — authority weight. “Does R8’s ratification of guides-as-concepts as a roadmap theme 15 update carry enough authority to void B.1/B.2’s guide_sections migration design, given R1/R2/R3/R5 amend decision records and R8’s schema-binding half is the connector register, not guides?” This lane reports the asymmetry rather than resolving it; it did not need resolving because §3 finds no requirement-level conflict.


  • Tracker Sections C, D, E, F (lines 245-497) not read beyond headings; only owner-named B.1/B.2/B.4/B.5/B.6 were read in full. D.1 (Sales Proposals workspace) may carry guide-adjacent requirements.
  • id-135 not verified directly. I verified id-144 (live function body) and id-162 (task file) first-hand; id-135’s “unified human + AI search, 31 subtasks” is taken from id-417’s description. My falsification of the “those replace it” claim rests on id-144 and id-162, which is sufficient for that claim but leaves id-135’s scope unaudited.
  • Prod DB not checked. All measurements are Platform staging (rbwqewalexrzgxtvcqrh). Client project DBs — where B.1/B.2’s actual 57-60-row guide corpus lives — were not queried at all. Any claim about the real client guide data is out of this lane’s evidence.
  • The /coverage and /guide/[slug] UI surfaces were grepped but not run or rendered; I did not confirm visually that guides display the empty state, only that the RPC returns no content rows.
  • DR-079 / DR-027 / DR-060 / DR-082 bodies not read — only titles, plus DR-019’s type posture. The L-concepts side of this report rests on bundle-doctrine.md and the live validator constant.
  • The ontology CV / controlled-vocabulary option was not evaluated as a membership-predicate substrate, though the census reportedly points at it. That belongs with lane A1’s ingest-model answer.
  • GitNexus CLI not used. Live-DB introspection plus grep answered every question directly; no call-graph question arose that needed it.
  • No writes of any kind. All SQL was SELECT/introspection; code was read-only; the two test suites were run without modification.