Commit graph

134 commits

Author SHA1 Message Date
b3e37c512a Fix query panel visibility and meta panel type counts
- Add /query proxy rule to nginx config (was missing, caused 404)
- Fix populateMetaPanel: call groupData.get() instead of reading empty
  groupData.map, and use ids.size (Set) not ids.length
- Update CLAUDE.md check #17 to reflect type counts now working

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 21:02:54 +01:00
4a92afb6b5 add ifcmcp config 2026-05-16 14:31:09 +01:00
7b17c8aafa Add Phase 3 browser test checklist to CLAUDE.md; file two bugs
- Document Forgejo/JS deployment paths, deploy commands, and services
- Add 18-item browser test checklist with known issues noted inline
- Correct check #17: hamburger button, type counts not shown (ifcurl-hwk)
- Create ifcurl-hwk: meta panel missing type counts
- Create ifcurl-6xq: query panel does not appear after selector resolves

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 14:29:45 +01:00
c05ed370aa Fix viewer camera offset: disable COORDINATE_TO_ORIGIN in web-ifc
web-ifc's COORDINATE_TO_ORIGIN=true shifts all model geometry so the first
element lands at origin (≈12m shift for simple-ifc). GetCoordinationMatrix
returns identity despite the shift, so engine_fragment can't compensate.
Camera URLs are in IFC world coords (per spec §5), but the model was in
shifted coords, causing the JS viewer and Python renderer to disagree.

Set COORDINATE_TO_ORIGIN: false in ifcLoader.setup() so model geometry
stays in IFC world coords, matching what IfcOpenShell outputs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 12:40:05 +01:00
03782ec9f7 Fix fetch-on-miss for PR commits: catch ValueError from GitPython directly
GitPython raises a plain ValueError from _parse_object_header when a commit
hash is missing, not BadObject, so the previous message-based retry guard
("not found in repository") never matched. Broaden the except clause to catch
(ValueError, BadObject, BadName) and drop the fragile string check. Extract
the fetch logic into _fetch_all_refs helper and apply the same retry to
diff_text. Add tests covering _fetch_all_refs, the retry-on-BadObject path,
and the no-retry-for-local-transport invariant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 08:56:07 +01:00
3937de2974 Fix PR diff early return and fetch branch commits on miss
ifcurl.js: URL-pattern cases (PR diff, commit page) now run before
the DOM-based file-view case, which also matches on Forgejo diff pages
and was causing an early return that skipped PR diff rendering.

git.py: fetch_ifc now retries with a full ref fetch when an immutable
ref (commit hash) is not found in the cached clone — PR branch commits
are absent from the initial default-branch clone and need a fetch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 01:12:15 +01:00
19fafba2e7 Merge pull request #7 from brunopostle/claude/add-query-clash-features-KerMN
Claude/add query clash features ker mn
2026-05-09 18:32:53 +02:00
Claude
fb20ca320d Enforce spec: validate query dot notation, improve tooltip
service.py: return 400 with a clear message when query= looks like a
bare property set name (starts with Pset_ or Qto_ but has no dot).
Catches the common mistake of writing Pset_WallCommon instead of
Pset_WallCommon.FireRating, giving feedback instead of silent empty results.

viewer.html: update query input placeholder and title to show the
expected formats (Name, Description for attributes; Pset_X.Prop for
property sets).

https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 15:26:07 +00:00
Claude
38161604f9 Viewer: query field and results table (ifcurl-2iv, ifcurl-4u3)
viewer-url.js: parseIfcUrl returns query field; buildIfcUrl gains optional
fifth query param, included in the QS when non-empty.

viewer.html: add 'query' text field (label + input) in toolbar row 2
after the visibility selector. Add #query-panel (fixed bottom-centre)
with a scrollable table showing GlobalId | value rows, a header
displaying the query path, and a close button.

viewer.js: populate queryInput from parsed URL on load; include query
in buildIfcUrl() wrapper; wire queryInput into Enter-key and focus/blur
listeners. Add applyQuery(srcUrl, queryPath) which calls GET /query,
populates the table, and shows the panel. Called from main() after
applySelector when both selector and query params are present.

viewer-url.test.js: add tests for parseIfcUrl query field, buildIfcUrl
with query, and buildIfcUrl omitting empty query.

https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 11:09:55 +00:00
Claude
ea0ad56bda Update beads state
https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 09:26:34 +00:00
Claude
8d13757c4d Viewer: add clash visibility mode (ifcurl-982)
viewer.html: add 'clash' option to the visibility <select> dropdown.

viewer.js: add clash branch in applySelector for both the simple
type-selector path and the complex server-side GUID path. Selected
elements are coloured 0xdc3232 (red, matching render.py's _CLASH_COLOR);
non-selected elements remain at their normal material colours, consistent
with highlight mode behaviour.

https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 09:03:11 +00:00
Claude
6ffc4a2b29 Simplify /clash: single selector, detect collisions within selected set
Drop selector_b — the endpoint now takes the URL's selector= and tests all
matched elements against each other, consistent with the spec's model.
Self-pairs and duplicates are filtered; requires at least 2 matched elements.

https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 08:57:54 +00:00
Claude
ccf692b168 Add /clash endpoint for geometry intersection detection (ifcurl-k0x)
render_service.py: _sandboxed_clash(ifc_bytes, selector_a, selector_b) uses
ifcopenshell.geom.tree.clash_collision_many for hard-clash detection (mesh-
level interpenetration, touching excluded). When selector_b is None, tests
set A against all other IfcProduct elements. Deduplicates pairs via frozenset.

render_service.py: /clash endpoint wraps _sandboxed_clash in the sandbox.

service.py: ClashRequest model, _clash_via_socket() for socket delegation,
and GET/POST /clash endpoints. URL selector= is set A; optional selector_b
body/query param is set B. Returns {"pairs": [["guidA", "guidB"], ...]}.
Reuses Tier 2 byte cache.

https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 08:53:51 +00:00
Claude
39243e343a Close ifcurl-8rf in beads
https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 08:46:40 +00:00
Claude
b560551f3c Implement clash visibility mode and /query endpoint (ifcurl-19h, ifcurl-8rf)
render.py: add _CLASH_COLOR and clash branch in _add_shape — selected
elements rendered in red, non-selected in normal material colours.

render_service.py: add _sandboxed_query(ifc_bytes, selector, query_path)
and /query endpoint. Dot-notation query_path splits into pset/property
(Pset_WallCommon.FireRating) or falls back to direct IFC attribute (Name).
Returns {GlobalId: str(value)}, excluding None and entity references.

service.py: add QueryRequest model, _query_via_socket() for socket
delegation, and GET/POST /query endpoints reusing Tier 2 byte cache.

https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 08:46:26 +00:00
Claude
83a8e087ed Sync beads after main merge
https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 08:41:33 +00:00
8e3171837c Merge pull request #6 from brunopostle/claude/add-query-clash-features-KerMN
Add beads for query and clash features
2026-05-09 10:35:04 +02:00
Claude
91b57ef37b Update clash beads: server-side detection via /clash endpoint
- Add ifcurl-k0x (P2): server /clash endpoint using IfcOpenShell geometry
  intersection (bbox pre-filter + mesh-level test), returns {pairs: [[gA,gB]]}
- Update ifcurl-982: viewer clash display now explicitly depends on ifcurl-k0x;
  GUIDs sourced from /clash rather than computed in JS
- Add dependency: ifcurl-982 blocked by ifcurl-k0x

https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 08:29:04 +00:00
Claude
56c36b51e9 Add beads for query and clash features
New issues:
- ifcurl-8rf (P2): Server /query endpoint + _sandboxed_query
- ifcurl-19h (P2): Renderer clash visibility mode
- ifcurl-2iv (P3): Viewer query results table (blocked on ifcurl-8rf)
- ifcurl-4u3 (P3): Viewer query creation/editing UI
- ifcurl-982 (P3): Viewer clash visibility mode display

https://claude.ai/code/session_01NBsytCd6L7UQPiKbcLn4kn
2026-05-09 08:09:10 +00:00
bbaec96d34 Merge pull request #5 from brunopostle/claude/review-spec-coverage-cM3AC
Add SessionStart hook to install bd and bootstrap beads in web sessions
2026-05-09 10:00:25 +02:00
Claude
b01c72b3ef .claude: add SessionStart hook to install bd and bootstrap beads
Installs bd (beads issue tracker) via go install and bootstraps the
embedded Dolt database from the git-tracked issues.jsonl on each fresh
web session, where the embeddeddolt/ directory is absent.

Bootstrap sequence:
  1. go install github.com/steveyegge/beads/cmd/bd@latest (if absent)
  2. Temporarily point sync.remote to the HTTP git origin so bootstrap
     can create the embedded Dolt schema (Dolt wire-protocol clone fails
     over HTTP/1.1 but that is expected and handled)
  3. Restore .beads/config.yaml and .beads/issues.jsonl from git before
     any bd auto-export can overwrite them
  4. bd config set issue_prefix ifcurl triggers auto-import of the full
     issues.jsonl into the initialised but empty database

Also adds bd to PATH via CLAUDE_ENV_FILE and sets beads.role=contributor
to suppress the role-not-configured warning.

https://claude.ai/code/session_01CKpkhWhzkzR5K5PDSR8N5F
2026-05-09 07:55:30 +00:00
d261648010 Merge pull request #4 from brunopostle/claude/review-spec-coverage-cM3AC
SPECIFICATION.md: add query parameter and visibility=clash
2026-05-09 09:28:50 +02:00
Claude
8ab6603a44 url.py, test_url.py: add query parameter and visibility=clash
- IfcUrl gains a query field (str | None) for dot-notation
  attribute/property paths (e.g. Pset_WallCommon.FireRating)
- visibility now accepts 'clash' in addition to the existing three modes
- to_string() serialises both new fields
- 10 new tests covering query parsing, pset paths, combined query+view,
  clash visibility, roundtrip serialisation, and the new spec examples

https://claude.ai/code/session_01CKpkhWhzkzR5K5PDSR8N5F
2026-05-09 07:27:35 +00:00
Claude
105824eb80 SPECIFICATION.md: add query parameter and visibility=clash
Adds two new parameters to address GitHub issues #2 and #3:

- `query`: dot-notation path (e.g. Pset_WallCommon.FireRating) that
  returns a {GlobalId: value} JSON object for the selected elements.
  Restricted to rooted entities; additive with view parameters so a
  viewer can show both a 3D view and a property table simultaneously.

- `visibility=clash`: visual-cue-only rendering style that marks
  selected elements with clash-indicator styling. No semantic claim;
  exports to BCF as highlight since BCF has no structural equivalent.

Updates §3, §7, and §8 accordingly.

https://claude.ai/code/session_01CKpkhWhzkzR5K5PDSR8N5F
2026-05-09 07:22:55 +00:00
4b96ee3206 viewer: show status hint when clip mode is active
Displays "Double-click model surface to place clip plane" in the status
bar when clip mode is toggled on, clears it when toggled off.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 22:30:24 +01:00
9afeae5d44 bcf_api: add topic filtering; documents_api: add GET /document-metadata
BCF list_topics now maps topic_status, assigned_to, label, modified_after,
modified_before query params to Forgejo issue API params.

documents_api adds GET /document-metadata/{document_id} which decodes the
document_id and proxies Forgejo's contents endpoint for file metadata.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 22:24:52 +01:00
95428eee25 beads: add OpenCDE completion issues (topic filtering, doc metadata, OAuth2, picker) 2026-04-29 21:39:54 +01:00
1578972492 beads: update issue tracker state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 20:48:01 +01:00
63a6b2bfa6 documents_api: implement OpenCDE Documents API 1.0
POST /documents/1.0/document-versions resolves document_ids (base64url
encoding of owner/repo/path) to versioned download URLs. Exposes only
git tags + the current HEAD commit — mirrors CDE conventions where only
released versions are visible, while still surfacing the WIP state.

version_number is the tag name for releases and short SHA for HEAD.
Tagged SHAs are deduplicated so HEAD at a tag doesn't create a duplicate.
Download URLs point at Forgejo's existing raw/commit endpoint.

Auth forwarded verbatim. No Go code, no Forgejo recompilation.
Proxy at /documents/ on the Forgejo hostname.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 20:27:25 +01:00
8821c70098 beads: close ifcurl-b1c 2026-04-29 19:39:22 +01:00
9e1a10e0b6 bcf_api: implement BCF 3.0 REST API as Python routes in the preview service
Stateless translation layer over Forgejo issues and comments. Auth is
forwarded verbatim (Authorization: Bearer), so Forgejo enforces per-user
permissions with no service token. Viewpoints are ifc:// URLs stored in
comment bodies; GUIDs are deterministically derived from Forgejo IDs and
are reversible without a lookup table.

Endpoints: GET/POST projects, topics, comments, viewpoints; PUT topic;
GET viewpoint snapshot (proxied through preview service).

Also adds ifc_url_to_bcf_viewpoint() to bcf.py (symmetric counterpart of
bcf_viewpoint_to_ifc_url), and fixes rate-limit state leaking between tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 19:38:34 +01:00
33c0292047 beads: close ifcurl-lwl 2026-04-29 19:21:48 +01:00
ee57e812e5 service: add GET /foundation/versions OpenCDE discovery endpoint
Returns the Foundation API 1.1 version document listing BCF 3.0 and
Documents 1.0 API base URLs. Public, no auth required. Derives the
public base URL from X-Forwarded-Host/X-Forwarded-Proto headers so it
works correctly behind an nginx/Caddy reverse proxy with no extra config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 19:20:54 +01:00
2e0a55f55a beads: close ifcurl-l50 2026-04-29 19:10:20 +01:00
2ad0816666 docs: document bcf_viewpoint_to_ifc_url() and IfcUrl.to_string()
Update SPECIFICATION.md §6 to clarify the isolate-visibility mapping
(DefaultVisibility=false + Exceptions). Add library usage examples to
README for to_string() and bcf_viewpoint_to_ifc_url().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 19:07:53 +01:00
930b8b5e32 bcf: add bcf_viewpoint_to_ifc_url() and IfcUrl.to_string()
Implements SPECIFICATION.md §6 BCF→ifc:// direction: parse a BCF 3.0
REST viewpoint dict (camera, clips, selection/visibility) and apply it
to a base IfcUrl to produce an ifc:// URL string.

IfcUrl.to_string() serialises any IfcUrl back to a valid ifc:// URL,
enabling round-trip parse→to_string for all URL forms.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 19:04:04 +01:00
9879ee9f3a readme: add OpenCDE phases to roadmap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 00:12:24 +01:00
8f4b5757e2 spec: add OpenCDE transport extension to ifc:// scheme
Extends the ifc:// URL scheme to address IFC documents hosted on
OpenCDE-compliant Common Data Environments, using document_id= and
version_index= query parameters as the transport signal and version
reference respectively. Adds §9 covering resolver workflow, OAuth2
discovery via Foundation API, caching rules, and federation notes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 23:33:52 +01:00
82756b5ebb Merge pull request #1 from OpeningDesign/forgejo/local-setup-docker
forgejo: add Docker-based local setup guide and Dockerfile
2026-04-28 00:02:33 +01:00
950349941c forgejo: add @thatopen/components-front, fix click-to-identify and model overview
Bundle OBCF (components-front) alongside OBC so Highlighter is sourced from the
correct package.  Update click handler to use item.getGuid() — GlobalId is no
longer in the attributes map in fragments 3.4.x.  Fix populateMetaPanel crash
(ClassificationGroupData now wraps ids in a .map property, not a plain object).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 00:01:19 +01:00
889645c2b2 forgejo: fix missing View in 3D button on commit file view pages
On /src/commit/{hash}/file.ifc pages, breadcrumb anchors match the
a[href*="/src/commit/"] selector before the Permalink anchor, returning
a directory URL that parseCommitHref rejects (no file path). Fix by
trying window.location.pathname first — it parses correctly when already
on a commit file URL — and only falling back to a Permalink anchor search
for branch/tag file views. Add a regression test for directory-level
commit hrefs returning null.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 20:31:43 +01:00
d60bd044dd forgejo: add JS unit tests, extract pure functions into viewer-util.js
Extract parseCommitHref, isSimpleTypeSelector, subtractIdMap, and
isCommitHash into a new viewer-util.js ES module so they can be tested
without a browser. Convert ifcurl.js from an IIFE to an ES module
importing from viewer-util.js; update footer.tmpl to type="module".

Add node:test suites for viewer-url.js (32 tests) and viewer-util.js
(28 tests). Add npm test script and document it in the build section.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 20:24:58 +01:00
Ryan Schultz
d7dd4f1ea1 forgejo: add Docker-based local setup guide and Dockerfile
Add forgejo/SETUP_LOCAL.md documenting a self-contained local deployment
of Forgejo + ifcurl on Windows using Docker Desktop. Covers Nginx reverse
proxy for PR diff images, correct Forgejo v15 custom paths (/data/gitea),
libosmesa6 for headless rendering, and a git URL rewrite so the ifcurl
container can clone repos from localhost:3000 via the Docker-internal
forgejo hostname.

Add docker/Dockerfile for the ifcurl preview service.

Link SETUP_LOCAL.md from README.md and forgejo/README.md.
2026-04-27 12:26:58 -05:00
a1a7a6c829 forgejo: handle ifc:// markdown links in JS, eliminate required Go compile
- ifcurl.js: scan a[href^="ifc://"] at page load and replace with preview
  figures — works with [title](ifc://...) syntax without any Go extension
- viewer.js: Issue button now emits [title](ifc://...) markdown link syntax
  instead of a bare URL, so shared views render as previews without the patch
- README: document no-rebuild quick setup path; Go patch section is now optional

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 08:25:34 +01:00
27156a5906 forgejo: extract footer.tmpl inline JS into ifcurl.js asset
footer.tmpl now just loads /assets/ifcurl.js; all injection logic lives in
the new ifcurl.js file alongside the other viewer assets. Update deploy
instructions in both READMEs; fix incorrect /etc/forgejo path in top-level README.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 07:36:57 +01:00
9c7b07e753 docs: reorganise README to lead with Forgejo features
Move visual diffs, inline previews, viewer, and collaboration workflow to
the top. ifc:// URL spec, Python library, and preview service follow as
supporting detail. Add missing items: storey isolation, ref autocomplete,
visibility dropdown, /select and /render_diff endpoints, cache CLI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 07:32:12 +01:00
7e9e814a4b viewer: add ifc:// URL links and clickable images to embedded snapshots
- ifc_url.go: wrap figcaption URL in <a href="ifc://"> for future protocol handler
- footer.tmpl: wrap diff snapshot images in viewer links; add ifc:// URL anchor below each snapshot (Cases 3 and 4)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 07:05:14 +01:00
4e84a2beda beads: update issue tracker state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 18:38:10 +01:00
36f528a254 viewer: extract inline JS into viewer.js
viewer.html was ~1250 lines of almost entirely JavaScript. The script
block is now a single <script type="module" src="./viewer.js"> tag,
leaving viewer.html as pure HTML/CSS (~238 lines).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 15:50:28 +01:00
3dd804ffc7 viewer: fix five P3 bugs (types, clip, ref nav, ortho, BCF snapshot)
- Types panel: fix count by iterating groupData directly (groupData.map
  was undefined — FragmentIdMap is the groupData value, not a wrapper)
- Clip planes: register OBC.Raycasters for the world before setupClipper
  so clipper.create(world) can raycast against the model surface
- Ref navigation: ▾ button now navigates when input already has a value;
  add change listener alongside input for cross-browser datalist coverage
- Orthographic projection: replace missing controls.setOrthoCamera() with
  world.camera.projection.set("Orthographic") + threeOrtho scale fix;
  refresh threeCamera reference after projection switch
- BCF export: capture rendererCanvas snapshot and include snapshot.png in
  the BCF zip with a <Snapshot> reference in markup.bcf

Closes: ifcurl-07d, ifcurl-1pa, ifcurl-66h, ifcurl-xy9, ifcurl-uo9

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 14:07:52 +01:00