diff --git a/.changeset/bcf-topic-not-issue-terminology.md b/.changeset/bcf-topic-not-issue-terminology.md new file mode 100644 index 0000000000..764dfeb301 --- /dev/null +++ b/.changeset/bcf-topic-not-issue-terminology.md @@ -0,0 +1,19 @@ +--- +"@ifc-lite/viewer": patch +"@ifc-lite/bcf": patch +"@ifc-lite/bcf-api": patch +"@ifc-lite/sdk": patch +"@ifc-lite/cli": patch +"@ifc-lite/mcp": patch +"@ifc-lite/sandbox": patch +--- + +Finish renaming the BCF "issues" language to "topics" across the app, docs, and package-facing text. Per the BCF-XML specification, `Topic` is the container element and `Issue` is only one `TopicType` value among several (Request, Comment, Error, Warning, Info); the previous patch fixed the BCF panel's own title, heading, empty-state copy, and topic-title placeholder, and left the rest of the product inconsistent. + +Remaining app-visible surfaces now fixed: the Analyze ribbon's "BCF issues" toggle button (a fourth site, alongside the command palette, main toolbar, and workspace-panel controls fixed previously), the compare panel's "Create BCF issue" affordance and "Issue for" header, the auto-created BCF project's default name (`_Issues` → `_Topics`, matching the BCF panel's own default), the landing-page hero animation's "Issue" step label, the MCP playground's BCF category blurb and example export path, and BCF-related copy across three in-app tours (`bcf`, `compare`, `clash`) — tour titles/descriptions plus five step titles/bodies. + +Docs updated to match: `docs/index.md`, `README.md`, `docs/guide/quickstart.md`, `docs/guide/bcf.md`, `docs/api/typescript.md`, and the CLI guide/reference's `bcf` examples (`--out topic.bcf`, `bcf list topics.bcf`), which also renamed the example filenames for consistency — they are illustrative only; the CLI has no default BCF filename. + +Also reworded now-inconsistent internal comments and JSDoc in the touched files, `@ifc-lite/bcf`'s package README and `createTopic` doc comment, `@ifc-lite/bcf-api`'s README, `@ifc-lite/sdk`'s `bim.bcf` namespace docs, `@ifc-lite/mcp`'s `bcf` tool docblock and fire-rating prompt template, and `@ifc-lite/sandbox`'s clash-to-BCF tool description — all comment/doc-only, no behavior change beyond the CLI's `bcf create` usage-message example (`--title "Issue"` → `--title "Missing door"`, matching the `--help` listing). + +Left deliberately unchanged: `bcfHelpers.tsx`'s `TOPIC_TYPES` list and every other real `TopicType` spec value (including the MCP `bcf` tool's `type` default and the sandbox playground's `topicType` default, both `'Issue'`), `ClashPanel`'s unrelated clash-detection "issues", GitHub issue-number references, and `registry.ts`'s `id: 'bcf'` panel key. diff --git a/.claude/skills/use-ifclite/cli-reference.md b/.claude/skills/use-ifclite/cli-reference.md index 2cda1daaff..83a91f59d1 100644 --- a/.claude/skills/use-ifclite/cli-reference.md +++ b/.claude/skills/use-ifclite/cli-reference.md @@ -91,9 +91,9 @@ Flags: `--json` · `--locale en|de|fr`. Exit 0 (pass) / 1 (fail). ## bcf ```bash -ifc-lite bcf create --title "Missing fire door" --description "Level 2" --out issue.bcf -ifc-lite bcf list issues.bcf -ifc-lite bcf add-comment --file issues.bcf --text "Fixed in rev 3" --out updated.bcf +ifc-lite bcf create --title "Missing fire door" --description "Level 2" --out topic.bcf +ifc-lite bcf list topics.bcf +ifc-lite bcf add-comment --file topics.bcf --text "Fixed in rev 3" --out updated.bcf ``` ## create diff --git a/README.md b/README.md index 0eaaa4ab4c..ddcb90a89f 100644 --- a/README.md +++ b/README.md @@ -243,7 +243,7 @@ Not sure? Start with the browser setup. You can add a server or switch engines l | Export to glTF / IFC / Parquet | + `@ifc-lite/export` | | Detect clashes | + `@ifc-lite/clash` | | Diff two model versions | + `@ifc-lite/diff` | -| BCF issue tracking | + `@ifc-lite/bcf` | +| BCF topic tracking | + `@ifc-lite/bcf` | | Filter and colorize in 3D by rules | + `@ifc-lite/lens` | | Build schedules and property tables | + `@ifc-lite/lists` | | Script models with the `bim.*` API | + `@ifc-lite/sdk` | diff --git a/apps/viewer/src/components/mcp/HeroScene.tsx b/apps/viewer/src/components/mcp/HeroScene.tsx index b02ff05285..5b11ed2e1d 100644 --- a/apps/viewer/src/components/mcp/HeroScene.tsx +++ b/apps/viewer/src/components/mcp/HeroScene.tsx @@ -78,7 +78,7 @@ export const HERO_STEPS: HeroStep[] = [ { verb: 'Standardize', line: 'bsdd_property_sets("IfcWall")', family: 'bSDD', overlay: { kind: 'psets', psets: ['Pset_WallCommon', 'Qto_WallBaseQuantities', 'Pset_ConcreteElementGeneral'] } }, { verb: 'Add', line: 'entity_create(IfcDoor)', family: 'Mutation' }, { verb: 'Section', line: 'viewer_set_section(z = 2.2)', family: 'Viewer' }, - { verb: 'Issue', line: 'bcf_topic_create("missing fire rating")', family: 'BCF', overlay: { kind: 'pin', ref: 'BCF #04' } }, + { verb: 'Flag', line: 'bcf_topic_create("missing fire rating")', family: 'BCF', overlay: { kind: 'pin', ref: 'BCF #04' } }, { verb: 'Inspect', line: 'viewer_describe_selection()', family: 'Viewer', overlay: { kind: 'card', ref: 'IfcWall #262', lines: ['Pset_WallCommon · IsExternal=true', 'FireRating=EI60 · 240 mm concrete'] } }, ]; diff --git a/apps/viewer/src/components/mcp/data.ts b/apps/viewer/src/components/mcp/data.ts index d7dcd50a9a..65ea8f37ac 100644 --- a/apps/viewer/src/components/mcp/data.ts +++ b/apps/viewer/src/components/mcp/data.ts @@ -63,7 +63,7 @@ export const CATEGORY_BLURBS: Record = { Geometry: 'Bounding boxes, volumes, areas — read from quantity sets.', Validation: 'IDS specs and a built-in model audit.', Mutation: 'Queue property/attribute writes; persist on save.', - BCF: 'Author and export buildingSMART issues + viewpoints.', + BCF: 'Author and export buildingSMART topics + viewpoints.', bSDD: 'Look up canonical class/property metadata.', Diff: 'Compare two loaded models — added/removed/changed.', Export: 'Dump to .ifc, CSV, JSON, glTF, IFCx, PDF.', @@ -618,7 +618,7 @@ export const EXAMPLES: Record> = { bcf_topic_update: { guid: '7e87d7f4-...', comment: 'Confirmed with the structural team.' }, bcf_topic_close: { guid: '7e87d7f4-...' }, bcf_viewpoint_create: { guid: '7e87d7f4-...', selection_global_ids: ['1AQAupaRP1txwK1AGiN61V'] }, - bcf_export: { file_path: '/tmp/issues.bcfzip' }, + bcf_export: { file_path: '/tmp/topics.bcfzip' }, bsdd_search: { query: 'wall' }, bsdd_class: { ifc_type: 'IfcWall' }, bsdd_property_sets: { ifc_type: 'IfcWall' }, diff --git a/apps/viewer/src/components/mcp/playground-dispatcher.ts b/apps/viewer/src/components/mcp/playground-dispatcher.ts index a85966a2e5..043c1be2fb 100644 --- a/apps/viewer/src/components/mcp/playground-dispatcher.ts +++ b/apps/viewer/src/components/mcp/playground-dispatcher.ts @@ -187,7 +187,7 @@ async function autoStageBcfDownload(): Promise = { }, async bcf_export(_m, args) { const project = getBcfProject(); - const filename = coerceFilename(args.file_path as string | undefined, 'bcfzip', 'issues'); + const filename = coerceFilename(args.file_path as string | undefined, 'bcfzip', 'topics'); const blob = await writeBCF(project); const file = playgroundFiles.add({ filename, mimeType: 'application/zip', size: blob.size, blob, @@ -1766,7 +1766,7 @@ function resolveIdsXml(args: Record): string | null { * * coerceFilename('wall_fire_rating.ids', 'ifc') → 'wall_fire_rating.ifc' * coerceFilename('/tmp/foo.bar/baz.csv', 'json') → 'baz.json' - * coerceFilename(undefined, 'bcfzip', 'issues') → 'issues.bcfzip' + * coerceFilename(undefined, 'bcfzip', 'topics') → 'topics.bcfzip' */ function coerceFilename( raw: string | undefined, diff --git a/apps/viewer/src/components/viewer/BCFPanel.tsx b/apps/viewer/src/components/viewer/BCFPanel.tsx index 5cbb2f5455..31ee7ea0b4 100644 --- a/apps/viewer/src/components/viewer/BCFPanel.tsx +++ b/apps/viewer/src/components/viewer/BCFPanel.tsx @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /** - * BCFPanel - BIM Collaboration Format issue management panel + * BCFPanel - BIM Collaboration Format topic management panel * * Provides: * - Topic list with filtering @@ -121,15 +121,15 @@ export function BCFPanel({ onClose }: BCFPanelProps) { if (models.size === 0) { // No models loaded, use date-based name const date = new Date().toISOString().split('T')[0]; - return `BCF_Issues_${date}`; + return `BCF_Topics_${date}`; } - // Use first model's name (without extension) + "_Issues" + // Use first model's name (without extension) + "_Topics" const firstModel = models.values().next().value; if (firstModel?.name) { const baseName = firstModel.name.replace(/\.(ifc|ifczip)$/i, ''); - return `${baseName}_Issues`; + return `${baseName}_Topics`; } - return `BCF_Issues_${new Date().toISOString().split('T')[0]}`; + return `BCF_Topics_${new Date().toISOString().split('T')[0]}`; }, [models]); // Initialize project if needed @@ -194,7 +194,7 @@ export function BCFPanel({ onClose }: BCFPanelProps) { setBcfLoading(true); const blob = await writeBCF(bcfProject); // Use project name, or generate from model name, or date-based fallback - const fileName = sanitizeFilename(bcfProject.name || getDefaultProjectName(), { fallback: 'issues' }); + const fileName = sanitizeFilename(bcfProject.name || getDefaultProjectName(), { fallback: 'topics' }); downloadBlob(blob, `${fileName}.bcfzip`); posthog.capture('bcf_exported', { topic_count: bcfProject.topics.size }); } catch (error) { @@ -383,7 +383,7 @@ export function BCFPanel({ onClose }: BCFPanelProps) {
-

BCF Issues

+

BCF Topics

{topics.length > 0 && ( {topics.length} diff --git a/apps/viewer/src/components/viewer/CommandPalette.tsx b/apps/viewer/src/components/viewer/CommandPalette.tsx index 94cc480288..ad110f5ea1 100644 --- a/apps/viewer/src/components/viewer/CommandPalette.tsx +++ b/apps/viewer/src/components/viewer/CommandPalette.tsx @@ -354,7 +354,7 @@ export function CommandPalette({ open, onOpenChange }: CommandPaletteProps) { action: () => { const s = useViewerStore.getState(); s.setLeftPanelCollapsed(!s.leftPanelCollapsed); } }, { id: 'panel:script', label: 'Script Editor', keywords: 'code automation console', category: 'Panels', icon: FileCode2, action: () => { activateBottomPanel('script'); } }, - { id: 'panel:bcf', label: 'BCF Issues', keywords: 'collaboration topics comments viewpoint', category: 'Panels', icon: MessageSquare, + { id: 'panel:bcf', label: 'BCF Topics', keywords: 'collaboration topics comments viewpoint', category: 'Panels', icon: MessageSquare, action: () => { activateRightPanel('bcf'); } }, { id: 'panel:ids', label: 'IDS Validation', keywords: 'information delivery specification check', category: 'Panels', icon: ClipboardCheck, action: () => { activateRightPanel('ids'); } }, diff --git a/apps/viewer/src/components/viewer/ComparePanel.tsx b/apps/viewer/src/components/viewer/ComparePanel.tsx index f6ea17c9e0..da909d6dbc 100644 --- a/apps/viewer/src/components/viewer/ComparePanel.tsx +++ b/apps/viewer/src/components/viewer/ComparePanel.tsx @@ -232,7 +232,7 @@ export function ComparePanel({ onClose }: ComparePanelProps) { }); }; - // Composing a BCF issue: collapse the diff chrome so the form owns the panel. + // Composing a BCF topic: collapse the diff chrome so the form owns the panel. // Gate on the selected row too, so a vanished selection can never leave the // panel empty (chrome hidden but no form to show). const bcfComposing = bcf.formOpen && !!selectedRow; @@ -265,8 +265,8 @@ export function ComparePanel({ onClose }: ComparePanelProps) { ) : ( <> {/* Diff chrome (run controls, counts, report, results, detail) — hidden - while composing a BCF issue so the form owns the panel. The user has - committed to raising an issue and the change context is already in the + while composing a BCF topic so the form owns the panel. The user has + committed to raising a topic and the change context is already in the pre-filled form, so re-running / exports / browsing only get in the way. */} {!bcfComposing && ( <> @@ -378,7 +378,7 @@ export function ComparePanel({ onClose }: ComparePanelProps) { > - Issue for + Topic for {selectedRow.name || selectedRow.ifcType} {selectedRow.ifcType.replace(/^Ifc/, '')} @@ -386,7 +386,7 @@ export function ComparePanel({ onClose }: ComparePanelProps) {
)} - {/* Raise a BCF issue from the focused change (#1199) */} + {/* Raise a BCF topic from the focused change (#1199) */} {selectedRow && ( handleToggleRightPanel('bcf')} > - BCF Issues + BCF Topics , options?: { includeSnapshot: boolean }) => void; onCancel: () => void; author: string; - /** Pre-fill the title (e.g. when raising an issue from a detected change). */ + /** Pre-fill the title (e.g. when raising a topic from a detected change). */ initialTitle?: string; /** Pre-fill the description. */ initialDescription?: string; @@ -141,7 +141,7 @@ export function BCFCreateTopicForm({ id="title" value={title} onChange={(e) => setTitle(e.target.value)} - placeholder="Brief description of the issue" + placeholder="Brief description of the topic" required />
diff --git a/apps/viewer/src/components/viewer/bcf/BCFTopicList.tsx b/apps/viewer/src/components/viewer/bcf/BCFTopicList.tsx index abef54ca44..576c96e0c4 100644 --- a/apps/viewer/src/components/viewer/bcf/BCFTopicList.tsx +++ b/apps/viewer/src/components/viewer/bcf/BCFTopicList.tsx @@ -186,7 +186,7 @@ export function BCFTopicList({ {isDefaultEmail && !editingEmail && (

- Set your email to identify your issues and comments + Set your email to identify your topics and comments

)} diff --git a/apps/viewer/src/components/viewer/compare/BcfFromChange.tsx b/apps/viewer/src/components/viewer/compare/BcfFromChange.tsx index 96f8dd4617..2a77509d6b 100644 --- a/apps/viewer/src/components/viewer/compare/BcfFromChange.tsx +++ b/apps/viewer/src/components/viewer/compare/BcfFromChange.tsx @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /** - * "Create BCF issue" affordance shown under the focused change (issue #1199). + * "Create BCF topic" affordance shown under the focused change (issue #1199). * Extracted from ComparePanel; the actual topic creation lives in the panel so * it can coordinate the BCF store + viewpoint capture. */ @@ -54,7 +54,7 @@ export function BcfFromChange({ return (
- BCF issue created: “{createdTitle}” + BCF topic created: “{createdTitle}” @@ -63,7 +63,7 @@ export function BcfFromChange({ } if (open) { - // Composing a BCF issue: the diff chrome is collapsed (ComparePanel), so the + // Composing a BCF topic: the diff chrome is collapsed (ComparePanel), so the // form owns the remaining height and scrolls internally — its actions stay // reachable instead of being clipped off the bottom of the panel. return ( @@ -86,7 +86,7 @@ export function BcfFromChange({
); diff --git a/apps/viewer/src/components/viewer/compare/useBcfFromChange.ts b/apps/viewer/src/components/viewer/compare/useBcfFromChange.ts index 878874e26e..97530e2375 100644 --- a/apps/viewer/src/components/viewer/compare/useBcfFromChange.ts +++ b/apps/viewer/src/components/viewer/compare/useBcfFromChange.ts @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /** - * Coordinates the "raise a BCF issue from a detected change" flow (#1199), + * Coordinates the "raise a BCF topic from a detected change" flow (#1199), * extracted from ComparePanel to keep it under the module-size house rule. * * Owns the create-form open/created state, captures a viewpoint (camera + @@ -91,7 +91,7 @@ export function useBcfFromChange( const state = useViewerStore.getState(); if (!state.bcfProject) { const first = modelList[0]?.name?.replace(/\.(ifc|ifczip)$/i, '') || 'Comparison'; - state.setBcfProject(createBCFProject({ name: `${first}_Issues` })); + state.setBcfProject(createBCFProject({ name: `${first}_Topics` })); } // Resolve the viewpoint first so the topic's source-file Header can be // derived from the models its selection references before it is stored. @@ -128,7 +128,7 @@ export function useBcfFromChange( setFormOpen(false); setCreatedTitle(topic.title); } catch (error) { - console.error('[compare] failed to create BCF issue from change', error); + console.error('[compare] failed to create BCF topic from change', error); } finally { submitInFlight.current = false; } diff --git a/apps/viewer/src/components/viewer/ribbon/tabs/AnalyzeTab.test.tsx b/apps/viewer/src/components/viewer/ribbon/tabs/AnalyzeTab.test.tsx new file mode 100644 index 0000000000..fda940633f --- /dev/null +++ b/apps/viewer/src/components/viewer/ribbon/tabs/AnalyzeTab.test.tsx @@ -0,0 +1,38 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +/** + * The Analyze ribbon tab's "Validate" group has its own toggle button for + * the BCF panel — a fourth site (alongside CommandPalette, MainToolbar, and + * useWorkspacePanelControls, all pinned elsewhere) that once read "BCF + * issues". Topic is the BCF-XML container element and Issue is only one + * TopicType value among several (Request, Comment, Error, Warning, Info), + * so "issues" narrowed and contradicted the spec (#4096/#4097). Pin the + * corrected label here too, so it can't regress silently. + */ + +import '@/test/setup-dom.js'; +import { afterEach, describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import { render, cleanup } from '@/test/render.js'; +import { AnalyzeTab } from './AnalyzeTab.js'; + +describe('AnalyzeTab — BCF ribbon button', () => { + afterEach(() => { + cleanup(); + }); + + it('labels the Validate-group BCF button "BCF topics", not "BCF issues"', () => { + const container = render(); + const labels = [...container.querySelectorAll('button')].map((b) => b.textContent ?? ''); + assert.ok( + labels.some((t) => /BCF topics/.test(t)), + `expected a button labelled "BCF topics"; got: ${JSON.stringify(labels)}`, + ); + assert.ok( + !labels.some((t) => /BCF issues/i.test(t)), + `found a button still labelled "BCF issues": ${JSON.stringify(labels)}`, + ); + }); +}); diff --git a/apps/viewer/src/components/viewer/ribbon/tabs/AnalyzeTab.tsx b/apps/viewer/src/components/viewer/ribbon/tabs/AnalyzeTab.tsx index 84afcfeb22..da1dbee2c7 100644 --- a/apps/viewer/src/components/viewer/ribbon/tabs/AnalyzeTab.tsx +++ b/apps/viewer/src/components/viewer/ribbon/tabs/AnalyzeTab.tsx @@ -45,7 +45,7 @@ export function AnalyzeTab() { handleToggleRightPanel('bcf')} /> diff --git a/apps/viewer/src/components/viewer/toolbar/useWorkspacePanelControls.ts b/apps/viewer/src/components/viewer/toolbar/useWorkspacePanelControls.ts index 285d18eaf1..7ea42f515a 100644 --- a/apps/viewer/src/components/viewer/toolbar/useWorkspacePanelControls.ts +++ b/apps/viewer/src/components/viewer/toolbar/useWorkspacePanelControls.ts @@ -276,7 +276,7 @@ export function useWorkspacePanelControls() { if (activeWorkspacePanels.has('script')) return 'Script Editor'; if (activeWorkspacePanels.has('lists')) return 'Lists'; if (activeWorkspacePanels.has('gantt')) return 'Schedule'; - if (activeWorkspacePanels.has('bcf')) return 'BCF Issues'; + if (activeWorkspacePanels.has('bcf')) return 'BCF Topics'; if (activeWorkspacePanels.has('ids')) return 'IDS Validation'; if (activeWorkspacePanels.has('lens')) return 'Lens Rules'; if (activeWorkspacePanels.has('clash')) return 'Clash Detection'; diff --git a/apps/viewer/src/lib/panels/registry.test.ts b/apps/viewer/src/lib/panels/registry.test.ts index 72200e5352..6463695ced 100644 --- a/apps/viewer/src/lib/panels/registry.test.ts +++ b/apps/viewer/src/lib/panels/registry.test.ts @@ -69,6 +69,18 @@ describe('workspacePanelForShortcutCode (Alt+digit routing #1200/#1208)', () => }); }); +// The BCF panel's title once read "BCF issues" — Topic is the BCF-XML +// element and Issue is only one TopicType value among several (Request, +// Comment, Error, Warning, Info), so "issues" narrowed and contradicted the +// spec (#4096). Pin the corrected label so it can't regress silently. +describe('BCF panel title', () => { + it('says "BCF topics", not "BCF issues" (#4096)', () => { + const bcf = WORKSPACE_PANELS.find((p) => p.id === 'bcf'); + assert.ok(bcf, 'expected a bcf panel entry in the registry'); + assert.strictEqual(bcf.title, 'BCF topics'); + }); +}); + // `isBottomPanel` gates `usePanelControls`' toggle routing (script / gantt / // lists go through `toggleBottomPanel`, everything else through the sidebar // dock). The test above only exercises 'script' (Digit8) and 'lists' diff --git a/apps/viewer/src/lib/panels/registry.ts b/apps/viewer/src/lib/panels/registry.ts index 37cb595c72..e5e956c13d 100644 --- a/apps/viewer/src/lib/panels/registry.ts +++ b/apps/viewer/src/lib/panels/registry.ts @@ -86,7 +86,7 @@ export const WORKSPACE_PANELS: readonly WorkspacePanelDef[] = [ // Alt+1..9 / Alt+0 — order frozen since #1200 for the first seven. { id: 'properties', title: 'Information', short: 'Info', Icon: Info, group: 'inspect', region: 'side' }, { id: 'compare', title: 'Compare models', short: 'Compare', Icon: GitCompareArrows, group: 'inspect', region: 'side' }, - { id: 'bcf', title: 'BCF issues', short: 'BCF', Icon: MessageSquare, group: 'review', region: 'side' }, + { id: 'bcf', title: 'BCF topics', short: 'BCF', Icon: MessageSquare, group: 'review', region: 'side' }, { id: 'ids', title: 'IDS validation', short: 'IDS', Icon: ClipboardCheck, group: 'review', region: 'side' }, { id: 'lens', title: 'Lens rules', short: 'Lens', Icon: Palette, group: 'review', region: 'side' }, { id: 'clash', title: 'Clash detection', short: 'Clash', Icon: Crosshair, group: 'review', region: 'side' }, diff --git a/apps/viewer/src/lib/tours/tours/bcf.ts b/apps/viewer/src/lib/tours/tours/bcf.ts index ef4462c2c7..b64478a174 100644 --- a/apps/viewer/src/lib/tours/tours/bcf.ts +++ b/apps/viewer/src/lib/tours/tours/bcf.ts @@ -15,7 +15,7 @@ import type { TourDefinition } from '../types'; export const BCF_TOUR: TourDefinition = { id: 'bcf', - title: 'Raise issues with BCF', + title: 'Raise topics with BCF', description: 'Flag a problem, capture viewpoints, and export a .bcfzip your whole team can open.', minutes: 3, version: 1, @@ -27,15 +27,15 @@ export const BCF_TOUR: TourDefinition = { kind: 'action', anchor: activityAnchor('bcf'), placement: 'left', - title: 'Open BCF issues', - body: 'BCF is the open format for sharing issues between BIM tools. Open the BCF panel from the sidebar rail, or press Alt+3.', + title: 'Open BCF topics', + body: 'BCF is the open format for sharing topics between BIM tools. Open the BCF panel from the sidebar rail, or press Alt+3.', gate: { predicate: (s) => s.bcfPanelVisible }, }, { id: 'frame-problem', kind: 'canvas', title: 'Frame the problem', - body: 'Click an element to select it and orbit so the issue is in view. The viewpoint you capture next records this selection with the camera.', + body: 'Click an element to select it and orbit so the topic is in view. The viewpoint you capture next records this selection with the camera.', // A stale selection must not auto-advance the step (same guard as the // welcome tour's select step). prepare: (store) => { @@ -50,7 +50,7 @@ export const BCF_TOUR: TourDefinition = { anchor: TOUR_ANCHORS.bcfNewTopic, panel: 'bcf', placement: 'left', - title: 'Create an issue', + title: 'Create a topic', body: 'Click +, give the topic a short title, and click Create Topic. A snapshot of your current view is attached automatically.', arm: (state, ctx) => { ctx.baseline.topics = state.bcfProject ? state.bcfProject.topics.size : 0; diff --git a/apps/viewer/src/lib/tours/tours/clash.ts b/apps/viewer/src/lib/tours/tours/clash.ts index 15b09dde96..651cb2e74b 100644 --- a/apps/viewer/src/lib/tours/tours/clash.ts +++ b/apps/viewer/src/lib/tours/tours/clash.ts @@ -31,7 +31,7 @@ let hadClashResultAtTourStart = 0; export const CLASH_TOUR: TourDefinition = { id: 'clash', title: 'Find clashes', - description: 'Detect overlapping elements, zoom to a clash, and hand it off as a BCF issue.', + description: 'Detect overlapping elements, zoom to a clash, and hand it off as a BCF topic.', minutes: 4, version: 1, panel: 'clash', @@ -146,7 +146,7 @@ export const CLASH_TOUR: TourDefinition = { panel: 'clash', placement: 'left', title: 'Hand it off', - body: 'BCF topic files the focused clash as an issue with a snapshot. Clear removes the highlights when you are done.', + body: 'BCF topic files the focused clash with a snapshot. Clear removes the highlights when you are done.', }, ], }; diff --git a/apps/viewer/src/lib/tours/tours/compare.ts b/apps/viewer/src/lib/tours/tours/compare.ts index 4ce6e705c1..6acc2ceb5f 100644 --- a/apps/viewer/src/lib/tours/tours/compare.ts +++ b/apps/viewer/src/lib/tours/tours/compare.ts @@ -113,7 +113,7 @@ export const COMPARE_TOUR: TourDefinition = { panel: 'compare', placement: 'left', title: 'See exactly what changed', - body: 'The detail lists before and after values; a moved element shows its Moved distance. Export a report or raise a BCF issue from here.', + body: 'The detail lists before and after values; a moved element shows its Moved distance. Export a report or raise a BCF topic from here.', }, ], }; diff --git a/apps/viewer/src/store/slices/bcfSlice.ts b/apps/viewer/src/store/slices/bcfSlice.ts index 387787a3ab..9a5d0df319 100644 --- a/apps/viewer/src/store/slices/bcfSlice.ts +++ b/apps/viewer/src/store/slices/bcfSlice.ts @@ -5,7 +5,7 @@ /** * BCF (BIM Collaboration Format) state slice * - * Manages BCF topics, comments, and viewpoints for issue tracking. + * Manages BCF topics, comments, and viewpoints. */ import type { StateCreator } from 'zustand'; diff --git a/docs/api/typescript.md b/docs/api/typescript.md index fb1ca15b82..cf8b5bc20d 100644 --- a/docs/api/typescript.md +++ b/docs/api/typescript.md @@ -829,7 +829,7 @@ For byte-reproducible **exported files**, seed the exporter too: builders that a ## @ifc-lite/bcf -BCF (BIM Collaboration Format) support for issue tracking. Implements BCF 2.1 and 3.0. +BCF (BIM Collaboration Format) support for topic tracking. Implements BCF 2.1 and 3.0. ### readBCF / writeBCF diff --git a/docs/guide/bcf.md b/docs/guide/bcf.md index b9564be8f5..c111586c6f 100644 --- a/docs/guide/bcf.md +++ b/docs/guide/bcf.md @@ -1,13 +1,13 @@ # BCF Collaboration -IFClite supports **BCF (BIM Collaboration Format)**, the buildingSMART standard for issue tracking in BIM projects. The `@ifc-lite/bcf` package implements BCF 2.1 and 3.0 specifications. +IFClite supports **BCF (BIM Collaboration Format)**, the buildingSMART standard for topic tracking in BIM projects. The `@ifc-lite/bcf` package implements BCF 2.1 and 3.0 specifications. ## What is BCF? -BCF allows teams to create, share, and manage issues (called **topics**) linked to specific locations and components in a BIM model. Each topic can include: +BCF allows teams to create, share, and manage **topics** linked to specific locations and components in a BIM model. Each topic can optionally be typed (Issue, Request, Comment, and more) and can include: - **Viewpoints** - Camera positions and component visibility snapshots -- **Comments** - Discussion threads on the issue +- **Comments** - Discussion threads on the topic - **Component references** - Links to specific IFC entities via GlobalId ## Quick Start @@ -72,7 +72,7 @@ const bcfBlob = await writeBCF(project); ## Viewpoints -Viewpoints capture the camera state and component visibility at the time an issue is created. IFClite provides utilities to convert between viewer camera state and BCF viewpoint format. +Viewpoints capture the camera state and component visibility at the time a topic is created. IFClite provides utilities to convert between viewer camera state and BCF viewpoint format. ### Creating Viewpoints @@ -233,7 +233,7 @@ In the IFClite viewer, BCF is integrated through the BCF panel: | Type | Description | |------|-------------| | `BCFProject` | Top-level container with topics map and version | -| `BCFTopic` | An issue with title, status, comments, and viewpoints | +| `BCFTopic` | A topic with title, status, comments, and viewpoints | | `BCFComment` | A comment on a topic with author and timestamp | | `BCFViewpoint` | Camera state, component visibility, and clipping planes | | `BCFComponents` | Selected, visible, and colored component references | diff --git a/docs/guide/cli.md b/docs/guide/cli.md index f4926ad6a2..e64bf25644 100644 --- a/docs/guide/cli.md +++ b/docs/guide/cli.md @@ -588,14 +588,14 @@ Returns pass/fail summary with exit code 0 (pass) or 1 (fail). Create, read, and manage BCF (BIM Collaboration Format) files. ```bash -# Create a new BCF issue -ifc-lite bcf create --title "Missing fire door" --description "Level 2, Room 201" --out issue.bcf +# Create a new BCF topic +ifc-lite bcf create --title "Missing fire door" --description "Level 2, Room 201" --out topic.bcf # List topics in a BCF file -ifc-lite bcf list issues.bcf +ifc-lite bcf list topics.bcf # Add a comment to a BCF file -ifc-lite bcf add-comment --file issues.bcf --text "Fixed in revision 3" --out updated.bcf +ifc-lite bcf add-comment --file topics.bcf --text "Fixed in revision 3" --out updated.bcf ``` --- diff --git a/docs/guide/quickstart.md b/docs/guide/quickstart.md index a681034003..528cd890bc 100644 --- a/docs/guide/quickstart.md +++ b/docs/guide/quickstart.md @@ -3,7 +3,7 @@ Get up and running with IFClite in under 5 minutes. Choose your path based on your use case. !!! tip "Beyond Single-Model Viewing" - IFClite also supports **multi-model federation** (loading and coordinating multiple IFC files), **BCF** (BIM Collaboration Format) for issue tracking, and **IDS** (Information Delivery Specification) for model validation. See the [Next Steps](#next-steps) section for links to these guides. + IFClite also supports **multi-model federation** (loading and coordinating multiple IFC files), **BCF** (BIM Collaboration Format) for topic tracking, and **IDS** (Information Delivery Specification) for model validation. See the [Next Steps](#next-steps) section for links to these guides. ## Choose Your Approach @@ -582,7 +582,7 @@ try { - [Rendering Guide](rendering.md) - WebGPU rendering features - [Query Guide](querying.md) - Query entities and properties - [Federation Guide](federation.md) - Multi-model loading and coordination -- [BCF Guide](bcf.md) - BIM Collaboration Format for issue tracking +- [BCF Guide](bcf.md) - BIM Collaboration Format for topic tracking - [IDS Guide](ids.md) - Information Delivery Specification for validation - [2D Drawing Guide](drawing-2d.md) - Generate 2D drawings from models - [Mutations Guide](mutations.md) - Programmatic model modifications diff --git a/docs/index.md b/docs/index.md index 464116924a..cb46e66ce1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -55,7 +55,7 @@ - **Extract data** like properties, quantities, relationships, and spatial structure - **Validate models** against IDS (Information Delivery Specification) rules - **Generate 2D drawings** like floor plans, sections, and elevations from 3D models -- **Collaborate** with BCF support for issues, viewpoints, and comments +- **Collaborate** with BCF support for topics, viewpoints, and comments - **Export** to glTF, IFC, CSV, or Parquet - **Work with multiple models** at once with federated selection and visibility - **Automate from the terminal** with the [ifc-lite CLI](guide/cli.md), including an MCP server for AI assistants diff --git a/packages/bcf-api/README.md b/packages/bcf-api/README.md index 959dc6fe8c..ec304bf4da 100644 --- a/packages/bcf-api/README.md +++ b/packages/bcf-api/README.md @@ -1,6 +1,6 @@ # @ifc-lite/bcf-api -REST client for [buildingSMART BCF API](https://github.com/buildingSMART/BCF-API) (OpenCDE) servers. Connects to a BCF server, authenticates via OAuth2, and pulls projects, topics, comments and viewpoints into the [`@ifc-lite/bcf`](https://www.npmjs.com/package/@ifc-lite/bcf) in-memory model — so server-hosted issues flow through the same code paths as imported `.bcfzip` files. +REST client for [buildingSMART BCF API](https://github.com/buildingSMART/BCF-API) (OpenCDE) servers. Connects to a BCF server, authenticates via OAuth2, and pulls projects, topics, comments and viewpoints into the [`@ifc-lite/bcf`](https://www.npmjs.com/package/@ifc-lite/bcf) in-memory model — so server-hosted topics flow through the same code paths as imported `.bcfzip` files. Works in the browser and in Node (uses the global `fetch`; injectable for tests). Implements the BCF API 2.1 routes. diff --git a/packages/bcf/README.md b/packages/bcf/README.md index 09652feba7..75c30a569e 100644 --- a/packages/bcf/README.md +++ b/packages/bcf/README.md @@ -1,6 +1,6 @@ # @ifc-lite/bcf -BCF (BIM Collaboration Format) support for IFClite. Reads and writes BCF 2.1 and 3.0 files — the issue-tracking format every BIM tool speaks (Revit, Archicad, Solibri, BIMcollab, etc.). +BCF (BIM Collaboration Format) support for IFClite. Reads and writes BCF 2.1 and 3.0 files — the topic-tracking format every BIM tool speaks (Revit, Archicad, Solibri, BIMcollab, etc.). ## Installation diff --git a/packages/bcf/src/index.ts b/packages/bcf/src/index.ts index e3aa7018b3..cf9ddb1768 100644 --- a/packages/bcf/src/index.ts +++ b/packages/bcf/src/index.ts @@ -6,7 +6,7 @@ * @ifc-lite/bcf - BIM Collaboration Format support * * This package provides BCF (BIM Collaboration Format) support for IFC-Lite. - * It implements BCF 2.1 and 3.0 specifications for issue tracking in BIM projects. + * It implements BCF 2.1 and 3.0 specifications for topic tracking in BIM projects. * * @see https://github.com/buildingSMART/BCF-XML * @see https://www.buildingsmart.org/standards/bsi-standards/bim-collaboration-format/ @@ -121,7 +121,7 @@ export function createBCFProject(options?: { } /** - * Create a new BCF topic (issue) + * Create a new BCF topic */ export function createBCFTopic(options: { title: string; diff --git a/packages/cli/src/commands/bcf.ts b/packages/cli/src/commands/bcf.ts index e120096734..a722332c7a 100644 --- a/packages/cli/src/commands/bcf.ts +++ b/packages/cli/src/commands/bcf.ts @@ -24,7 +24,7 @@ export async function bcfCommand(args: string[]): Promise { const description = getFlag(args, '--description'); const author = getFlag(args, '--author') ?? 'cli@ifc-lite.com'; const outPath = getFlag(args, '--out'); - if (!title) fatal('Usage: ifc-lite bcf create --title "Issue" [--description "..."] [--author email] --out file.bcf'); + if (!title) fatal('Usage: ifc-lite bcf create --title "Missing door" [--description "..."] [--author email] --out file.bcf'); if (!outPath) fatal('--out is required for BCF creation'); const project = await bcf.createProject({ name: 'CLI Project' }); diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 23a44e1d08..620f7556af 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -150,7 +150,7 @@ const HELP = ` ifc-lite diagnose-geometry model.ifc --type IfcWall ifc-lite diagnose-geometry model.ifc --product 0YvCT2_$X3_xJG3rzD8L_8 ifc-lite ids model.ifc requirements.ids --json - ifc-lite bcf create --title "Missing door" --out issue.bcf + ifc-lite bcf create --title "Missing door" --out topic.bcf ifc-lite clash model.ifc --matrix --json ifc-lite clash model.ifc --a "IfcDuct*|IfcPipe*" --b "IfcWall*" --mode clearance --clearance 0.05 ifc-lite clash model.ifc --matrix --bcf clashes.bcfzip diff --git a/packages/mcp/src/prompts/templates.ts b/packages/mcp/src/prompts/templates.ts index b644a18e13..fcc8f97ef4 100644 --- a/packages/mcp/src/prompts/templates.ts +++ b/packages/mcp/src/prompts/templates.ts @@ -62,7 +62,7 @@ export const findFireRatedDoors: Prompt = { `2. For each non-compliant door, call \`bcf_topic_create\` titled "Fire rating below ${minimum} on " with the GlobalId in the description.`, `3. Attach a viewpoint with the door selected via \`bcf_viewpoint_create\`.`, `4. Report a summary of how many doors fail and the top 5 by name.`, - `5. Offer to export the BCF via \`bcf_export\` to ./fire-rating-issues.bcfzip.`, + `5. Offer to export the BCF via \`bcf_export\` to ./fire-rating-topics.bcfzip.`, ].join('\n')), ], }; diff --git a/packages/mcp/src/tools/bcf.ts b/packages/mcp/src/tools/bcf.ts index aacb701911..880dd5137c 100644 --- a/packages/mcp/src/tools/bcf.ts +++ b/packages/mcp/src/tools/bcf.ts @@ -7,7 +7,7 @@ * * Topics live inside a per-session BCF project that's lazy-created on first * write. We keep the project per ToolContext (server-wide, not per-model) - * so an agent can collect issues across federated models, then export a + * so an agent can collect topics across federated models, then export a * single .bcfzip via `bcf_export`. */ diff --git a/packages/sandbox/src/bridge-clash.ts b/packages/sandbox/src/bridge-clash.ts index 3e133b1153..d29c984f05 100644 --- a/packages/sandbox/src/bridge-clash.ts +++ b/packages/sandbox/src/bridge-clash.ts @@ -223,7 +223,7 @@ export function buildClashNamespace(): NamespaceSchema { returns: 'value', llmSemantics: { taskTags: ['inspect'], - useWhen: 'Cluster a clash result into BCF-ready groups before exporting issues.', + useWhen: 'Cluster a clash result into BCF-ready groups before exporting topics.', }, }, { diff --git a/packages/sdk/src/namespaces/bcf.ts b/packages/sdk/src/namespaces/bcf.ts index cca093ecf7..3a3776e851 100644 --- a/packages/sdk/src/namespaces/bcf.ts +++ b/packages/sdk/src/namespaces/bcf.ts @@ -7,7 +7,7 @@ * * Full access to @ifc-lite/bcf for reading/writing BCF files, * managing collaboration data, creating viewpoints, and - * converting between IDS reports and BCF issues. + * converting between IDS reports and BCF topics. */ // ============================================================================ @@ -101,10 +101,10 @@ export class BCFNamespace { } // -------------------------------------------------------------------------- - // Topic (issue) management + // Topic management // -------------------------------------------------------------------------- - /** Create a new topic (issue). */ + /** Create a new topic. */ async createTopic(options: TopicOptions): Promise { const mod = await loadBCF(); return (mod.createBCFTopic as AnyFn)({ @@ -261,7 +261,7 @@ export class BCFNamespace { // IDS → BCF conversion // -------------------------------------------------------------------------- - /** Convert an IDS validation report into BCF issues (one topic per failed spec). */ + /** Convert an IDS validation report into BCF topics (one topic per failed spec). */ async createFromIDSReport(report: unknown, options?: IDSBCFOptions): Promise { const mod = await loadBCF(); return (mod.createBCFFromIDSReport as AnyFn)(report, options);