diff --git a/docs/adr/0184-ontology-provenance-explorer.md b/docs/adr/0184-ontology-provenance-explorer.md index 5b9c254af..42267ffa9 100644 --- a/docs/adr/0184-ontology-provenance-explorer.md +++ b/docs/adr/0184-ontology-provenance-explorer.md @@ -28,6 +28,22 @@ 8. Node type uses shape plus text (never color alone). Every edge carries both endpoint type codes and IDs, so heterogeneous catalogs remain unambiguous even if UUIDs collide. Keyboard users can select every visible node and edge. The graph SVG has no enclosing ARIA `img`; native browser text layout wraps complete node labels instead of truncating or estimating character widths. Exact-value table, CSV, JSON-LD, and print expose the same authorized visible graph. JSON-LD emits the source-to-target property assertion directly and describes its evidence-bearing edge as an RDF reified statement with exact `rdf:subject`, `rdf:predicate`, and `rdf:object`; it does not make the edge resource itself the relationship subject. JSON-LD represents system time with `prov:generatedAtTime` and non-null validity bounds as OWL-Time `time:Instant` values using `time:inXSDDateTimeStamp`; it omits unavailable bounds rather than inventing them. 9. Synthetic Storybook frames cover desktop, narrow exact-value-first, node drawer, edge drawer, legend, empty, truncated, denied, stale, and rejected states. No confidential Figma content enters the repository. Storybook inventory records the implementation surface; frame IDs are not copied from the confidential design file (ADR 0002). +**Search/export clarification (2026-09-05):** Search filters direct JSON-LD +assertions by the retained typed source, property IRI, and typed target, not +only by the presence of their subject node. A retained node must not carry a +relationship excluded from the visible edge list, including after continuation +has combined singleton assertions into arrays. Keep its labels, times, truth, +and authorized Voice derivation metadata intact. This is a projection of the +already-authorized response, not a new authorization or inference boundary. + +CSV is a spreadsheet-facing rendering of the same authorized evidence, so +untrusted labels and evidence values must remain literal data when opened in a +spreadsheet. Neutralize formula-triggering ASCII, control, null, and supported +locale-sensitive full-width prefixes before CSV quoting, and quote both CR and +LF-bearing fields. This follows OWASP ASVS 5.0.0 requirement v5.0.0-1.2.10 and +the OWASP CSV Injection/WSTG guidance; it changes only export encoding, never +the authoritative value stored in PostgreSQL or represented by JSON-LD. + **Consequences:** - Event Lineage and ontology neighborhood stay distinct product capabilities. @@ -55,5 +71,11 @@ Knublauch, H., & Kontokostas, D. (Eds.). (2017). *Shapes constraint language (SH World Wide Web Consortium. (2024). *Web content accessibility guidelines (WCAG) 2.2* (W3C Recommendation). https://www.w3.org/TR/WCAG22/ +Open Worldwide Application Security Project. (2025). *OWASP application security verification standard 5.0.0*. https://owasp.org/www-project-application-security-verification-standard/ + +Open Worldwide Application Security Project. (n.d.). *CSV injection*. https://owasp.org/www-community/attacks/CSV_Injection + +Open Worldwide Application Security Project. (n.d.). *Testing for CSV injection* (WSTG-INPV-21). https://wstg.owasp.org/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/21-Testing_for_CSV_Injection/ + Open Worldwide Application Security Project. (2023). *API1:2023 broken object level authorization*. https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/ diff --git a/docs/development-loop-20260905-filter.json b/docs/development-loop-20260905-filter.json new file mode 100644 index 000000000..6d3a9b1d2 --- /dev/null +++ b/docs/development-loop-20260905-filter.json @@ -0,0 +1,4115 @@ +{ + "observed_at_utc": "2026-09-05T08:48:46.186264+00:00", + "main": "83eba56149eb802cd63642c507c324c9976ec78e", + "scope": "Remote metadata only; last 100 reviews and first 100 threads per PR. Authority paths reuse earlier exact immutable heads only; null means not re-audited. No review bodies or runtime records.", + "prs": [ + { + "pr": 934, + "title": "fix(ontology): preserve singleton relations across export pages", + "head": "3060dd7000791160c2bcc98351af129899ff32ff", + "base": "fix/voice-export-authority-20260828", + "base_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0256-evidence-bearing-voice-combinations.md", + "status": "modified" + } + ] + }, + { + "pr": 933, + "title": "fix(actions): preserve draft and close cancellation contract", + "head": "de4e6cf9a48b042af0bb1128fa9b194abd1952a5", + "base": "docs/public-surface-deepwiki", + "base_sha": "00e90e03ae1afb7f13ae843dd578694d0f72b325", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [] + }, + { + "pr": 932, + "title": "feat(i18n): consume published Customer Master screen copy", + "head": "fe01453821105e62274a754797f6bf51a2b9ae7d", + "base": "feat/i18n-versioned-translation-ledger", + "base_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0362-versioned-ui-translation-ledger.md", + "status": "modified" + } + ] + }, + { + "pr": 929, + "title": "feat: establish versioned UI translation ledger foundation", + "head": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 3, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0362-versioned-ui-translation-ledger.md", + "status": "added" + }, + { + "path": "migrations/0246_ui_translation_ledger.sql", + "status": "added" + }, + { + "path": "migrations/0247_ui_translation_truncate_guard.sql", + "status": "added" + }, + { + "path": "migrations/rollback/0246_ui_translation_ledger.sql", + "status": "added" + }, + { + "path": "migrations/rollback/0247_ui_translation_truncate_guard.sql", + "status": "added" + } + ] + }, + { + "pr": 928, + "title": "feat(reports): leftover-map origin on leftover-map pair independently of leftover-map leftover-axis leftover-map origin (v2.116.0)", + "head": "322b58247e933592ceb6d6eab6cac258ee5335cd", + "base": "feat/leftover-map-axis-origin-badge-v21150", + "base_sha": "34595e41ee65b89a468efeebf64fee86eff881d9", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0358-leftover-map-axis-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0359-leftover-map-list-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 927, + "title": "feat(reports): leftover-map origin on leftover-map leftover-axis independently of leftover-map comparison leftover-axis leftover-map origin (v2.115.0)", + "head": "34595e41ee65b89a468efeebf64fee86eff881d9", + "base": "feat/leftover-map-compare-axis-origin-badge-v21140", + "base_sha": "ede308929b20f24a56c5ff3ae2211dd84d20f3ae", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0346-leftover-map-axis-tick-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0357-leftover-map-compare-axis-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0358-leftover-map-axis-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 926, + "title": "feat(reports): leftover-map origin on leftover-map comparison leftover-axis independently of leftover-map comparison graphic leftover-map origin (v2.114.0)", + "head": "ede308929b20f24a56c5ff3ae2211dd84d20f3ae", + "base": "feat/leftover-map-compare-plot-origin-badge-v21130", + "base_sha": "76ebcb10a72955a68c616c02e6e0732db0800f93", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0345-leftover-map-compare-axis-tick-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0356-leftover-map-compare-plot-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0357-leftover-map-compare-axis-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 925, + "title": "docs(release): define immutable supply-chain boundary", + "head": "8cbaad528c9aaa8d4e356db1577b932fa85ac686", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0361-immutable-release-supply-chain-boundary.md", + "status": "added" + }, + { + "path": "docs/adr/README.md", + "status": "modified" + } + ] + }, + { + "pr": 921, + "title": "feat(reports): leftover-map origin on leftover-map comparison graphic independently of leftover-map graphic leftover-map origin (v2.113.0)", + "head": "76ebcb10a72955a68c616c02e6e0732db0800f93", + "base": "feat/leftover-map-plot-origin-badge-v21120", + "base_sha": "d54c5611cc693bb7a85e9164814761417ccb563e", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0344-leftover-map-compare-plot-tick-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0356-leftover-map-compare-plot-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 920, + "title": "feat(reports): leftover-map origin on leftover-map graphic independently of leftover-map comparison leftover-pair leftover-map criterion leftover-map origin leftover-map item coordinates (v2.112.0)", + "head": "d54c5611cc693bb7a85e9164814761417ccb563e", + "base": "feat/leftover-map-compare-list-criterion-origin-badge-v21110", + "base_sha": "a91d2ec56bad922f9159e17649f77d229a0f98d3", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0343-leftover-map-plot-tick-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0354-leftover-map-compare-list-criterion-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0355-leftover-map-plot-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 919, + "title": "refactor(operator): name bounded entry points and validate Keyman admissions", + "head": "caf8ee0f576eb23dc80d907fccfdcd6a4cecb232", + "base": "fix/contextual-orchestrator-owner-boundary", + "base_sha": "e5711282c48cc20d0a88fb56a9e382d500989c72", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0082-bounded-keyman-backfill.md", + "status": "modified" + } + ] + }, + { + "pr": 918, + "title": "feat(reports): leftover-map origin on leftover-map comparison leftover-pair leftover-map criterion leftover-map item coordinates independently of leftover-map comparison leftover-pair leftover-map post leftover-map origin leftover-map person coordinates (v2.111.0)", + "head": "a91d2ec56bad922f9159e17649f77d229a0f98d3", + "base": "feat/leftover-map-compare-list-post-origin-badge-v21100", + "base_sha": "8192b48560a919c800ec47927adc966179a2b572", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0342-leftover-map-compare-list-criterion-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0354-leftover-map-compare-list-criterion-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 917, + "title": "feat(reports): leftover-map origin on leftover-map comparison leftover-pair leftover-map post leftover-map person coordinates independently of leftover-map pair leftover-map post leftover-map origin leftover-map person coordinates (v2.110.0)", + "head": "8192b48560a919c800ec47927adc966179a2b572", + "base": "feat/leftover-map-list-criterion-origin-badge-v21090", + "base_sha": "7978e92561e16a3ea4e2837fef1f35fe0bec3f3c", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0341-leftover-map-compare-list-post-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0353-leftover-map-compare-list-post-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 916, + "title": "feat(reports): leftover-map origin on leftover-map pair leftover-map criterion leftover-map item coordinates independently of leftover-map pair leftover-map post leftover-map origin leftover-map person coordinates (v2.109.0)", + "head": "7978e92561e16a3ea4e2837fef1f35fe0bec3f3c", + "base": "feat/leftover-map-list-post-origin-badge-v21080", + "base_sha": "371bb82cea8437f907249d6e8b166f63dfe5bb8e", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0340-leftover-map-list-criterion-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0352-leftover-map-list-criterion-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 915, + "title": "fix(lineage): bind dynamic evaluations to substantive criteria", + "head": "8c74712f2af4acf76871c71a9fd72c6aa2912f4a", + "base": "feat/dichotomous-measurement-policy", + "base_sha": "c316bfbde8644feda7e49579d43cc162e99b0bad", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0355-dynamic-evaluation-lineage.md", + "status": "added" + } + ] + }, + { + "pr": 914, + "title": "refactor(activity): qualify Valkey activity identifiers", + "head": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": false, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": true, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0363-canonical-activity-stream-identity.md", + "status": "added" + }, + { + "path": "docs/adr/README.md", + "status": "modified" + } + ] + }, + { + "pr": 913, + "title": "feat(reports): leftover-map origin on leftover-map pair leftover-map post leftover-map person coordinates independently of leftover-map comparison graphic leftover-map post leftover-map origin leftover-map person coordinates (v2.108.0)", + "head": "371bb82cea8437f907249d6e8b166f63dfe5bb8e", + "base": "feat/leftover-map-compare-plot-criterion-origin-badge-v21070", + "base_sha": "2ac677bae522eb1925edc6bd105f1f57a287f73e", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0339-leftover-map-list-post-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0351-leftover-map-list-post-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 912, + "title": "feat(reports): leftover-map origin on leftover-map comparison graphic leftover-map criterion leftover-map item coordinates independently of leftover-map comparison graphic leftover-map post leftover-map origin leftover-map person coordinates (v2.107.0)", + "head": "2ac677bae522eb1925edc6bd105f1f57a287f73e", + "base": "feat/leftover-map-compare-plot-post-origin-badge-v21060", + "base_sha": "f2a1860185714d2921162a754425065d867bcce6", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0336-leftover-map-compare-plot-criterion-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0350-leftover-map-compare-plot-criterion-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 911, + "title": "fix(license): replace psycopg2 synchronous PostgreSQL boundary", + "head": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": false, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": true, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0366-synchronous-postgresql-default-tls.md", + "status": "added" + } + ] + }, + { + "pr": 909, + "title": "fix(customer): keep malformed Customer Master hierarchies visible", + "head": "e82aed38c0997588529e21fe0e1bf4159f3c198c", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0364-authenticated-browser-request-boundary.md", + "status": "added" + }, + { + "path": "docs/adr/0365-customer-master-malformed-hierarchy.md", + "status": "added" + }, + { + "path": "docs/adr/README.md", + "status": "modified" + } + ] + }, + { + "pr": 908, + "title": "docs: refresh public README and Pages navigation", + "head": "00e90e03ae1afb7f13ae843dd578694d0f72b325", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [] + }, + { + "pr": 907, + "title": "fix(customer): keep malformed affiliate hierarchies visible", + "head": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": false, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": true, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [] + }, + { + "pr": 904, + "title": "refactor(ddd): remove obsolete direct CalDAV boundary", + "head": "09d7be51a6b599769fb78371c9995a99d7df6974", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [] + }, + { + "pr": 903, + "title": "fix(ui): make lineage group order locale-independent", + "head": "e325b3f63fdb9c34a7c62ae58045ec36e34b1879", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [] + }, + { + "pr": 902, + "title": "feat(measurement): add dichotomous instrument policy contract", + "head": "c316bfbde8644feda7e49579d43cc162e99b0bad", + "base": "fix/contextual-orchestrator-owner-boundary", + "base_sha": "e5711282c48cc20d0a88fb56a9e382d500989c72", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0301-dichotomous-measurement-policy.md", + "status": "added" + } + ] + }, + { + "pr": 901, + "title": "docs(gaps): refresh protected delivery evidence", + "head": "d44cd875a93cb929b6e30b744976d2c19e67d981", + "base": "fix/voice-export-authority-20260828", + "base_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [] + }, + { + "pr": 899, + "title": "refactor(ddd): restore contextual-orchestrator ownership boundary", + "head": "e5711282c48cc20d0a88fb56a9e382d500989c72", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0300-contextual-orchestrator-owner-boundary.md", + "status": "added" + } + ] + }, + { + "pr": 897, + "title": "feat(analysis): seed Running TEPP accepted receipts (v2.29.0)", + "head": "c4194085f7bc0c7383f994da81d6a8146b695dc8", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0219-tepp-terminal-result-lifecycle.md", + "status": "modified" + } + ] + }, + { + "pr": 893, + "title": "feat(reports): leftover-map origin on leftover-map comparison graphic leftover-map post leftover-map person coordinates independently of leftover-map graphic leftover-map post leftover-map origin leftover-map person coordinates (v2.106.0)", + "head": "f2a1860185714d2921162a754425065d867bcce6", + "base": "feat/leftover-map-plot-post-origin-badge-v21050", + "base_sha": "c941929c7244f64e31e5ceca8b3c6f6bcb1e3541", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0337-leftover-map-compare-plot-post-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0349-leftover-map-compare-plot-post-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 892, + "title": "feat(reports): leftover-map origin on leftover-map graphic leftover-map post leftover-map person coordinates independently of leftover-map criterion leftover-map item coordinates (v2.105.0)", + "head": "c941929c7244f64e31e5ceca8b3c6f6bcb1e3541", + "base": "feat/leftover-map-plot-criterion-origin-badge-v21040", + "base_sha": "47dd988d6b5cdea713b163b40702235b65af5ffe", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0338-leftover-map-plot-post-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0348-leftover-map-plot-post-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 891, + "title": "feat(reports): leftover-map origin on leftover-map graphic leftover-map criterion leftover-map item coordinates independently of leftover-map person coordinates (v2.104.0)", + "head": "47dd988d6b5cdea713b163b40702235b65af5ffe", + "base": "feat/leftover-map-axis-tick-origin-badge-v21030", + "base_sha": "4bfb490d3e2bd8dd74caabaf2922ac3f6755749a", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0335-leftover-map-plot-criterion-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0346-leftover-map-axis-tick-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0347-leftover-map-plot-criterion-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 889, + "title": "feat(reports): leftover-map leftover-axis origin ticks independently of leftover-map axis share and leftover-map singular values (v2.103.0)", + "head": "4bfb490d3e2bd8dd74caabaf2922ac3f6755749a", + "base": "feat/leftover-map-compare-axis-tick-origin-badge-v21020", + "base_sha": "7637fc8bbe165be297794a74187aa1065e82486c", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0330-leftover-map-axis-tick-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0334-leftover-map-axis-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0345-leftover-map-compare-axis-tick-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0346-leftover-map-axis-tick-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 888, + "title": "feat(ask): stage exact authorized semantic index", + "head": "e5f38f3bda1caa1d48975204918c994a6a3dff3f", + "base": "feat/dashboard-case-metrics", + "base_sha": "f40e4ed8020a7db4099730d558da942a0f331614", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 3, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0224-canonical-compose-project.md", + "status": "modified" + }, + { + "path": "docs/adr/0272-twenty-millisecond-read-slo.md", + "status": "modified" + }, + { + "path": "docs/adr/0279-global-ask-exact-semantic-index.md", + "status": "added" + }, + { + "path": "docs/adr/README.md", + "status": "modified" + }, + { + "path": "migrations/0274_exact_embedding_projection.sql", + "status": "added" + }, + { + "path": "migrations/0275_global_ask_exact_authorization_version.sql", + "status": "added" + } + ] + }, + { + "pr": 887, + "title": "feat(reports): leftover-map comparison leftover-axis origin ticks independently of leftover-map axis share and leftover-map singular values (v2.102.0)", + "head": "7637fc8bbe165be297794a74187aa1065e82486c", + "base": "feat/leftover-map-compare-plot-tick-origin-badge-v21010", + "base_sha": "4a31a41f9036cad4ba35ed16b8fdf1c1212e4847", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0329-leftover-map-compare-axis-tick-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0333-leftover-map-compare-axis-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0344-leftover-map-compare-plot-tick-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0345-leftover-map-compare-axis-tick-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 886, + "title": "feat(reports): leftover-map comparison graphic leftover-map axis origin ticks independently of leftover-map axis share and leftover-map singular values (v2.101.0)", + "head": "4a31a41f9036cad4ba35ed16b8fdf1c1212e4847", + "base": "feat/leftover-map-plot-tick-origin-badge-v21000", + "base_sha": "7a6c0384f4d82544541b6af70cf178c51ed60d62", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0328-leftover-map-compare-plot-tick-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0331-leftover-map-compare-plot-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0343-leftover-map-plot-tick-origin-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0344-leftover-map-compare-plot-tick-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 885, + "title": "feat(reports): leftover-map graphic leftover-map axis origin ticks independently of leftover-map axis share and leftover-map singular values (v2.100.0)", + "head": "7a6c0384f4d82544541b6af70cf178c51ed60d62", + "base": "feat/leftover-map-compare-list-criterion-coordinates-v2990", + "base_sha": "bcbb7ce03f92304ccdc34fb014a8db8e3bf8a659", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0327-leftover-map-plot-tick-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0332-leftover-map-plot-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0342-leftover-map-compare-list-criterion-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0343-leftover-map-plot-tick-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 884, + "title": "feat(reports): leftover-map item coordinates on leftover-map comparison leftover pair leftover-map criterion independently of leftover-map comparison leftover pair leftover-map post leftover-map person coordinates (v2.99.0)", + "head": "bcbb7ce03f92304ccdc34fb014a8db8e3bf8a659", + "base": "feat/leftover-map-compare-list-post-coordinates-v2980", + "base_sha": "bdd48e23a16358b91a652e45c4373c6f45e389fa", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0267-leftover-map-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0302-leftover-map-compare-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0341-leftover-map-compare-list-post-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0342-leftover-map-compare-list-criterion-coordinates.md", + "status": "added" + } + ] + }, + { + "pr": 883, + "title": "feat(reports): leftover-map person coordinates on leftover-map comparison leftover pair leftover-map post independently of leftover-map comparison leftover pair leftover-map criterion leftover-map item coordinates (v2.98.0)", + "head": "bdd48e23a16358b91a652e45c4373c6f45e389fa", + "base": "feat/leftover-map-list-criterion-coordinates-v2970", + "base_sha": "094d1a0c8bcfd4b351f9665c47a84c510cbab94d", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 3, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0267-leftover-map-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0302-leftover-map-compare-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0340-leftover-map-list-criterion-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0341-leftover-map-compare-list-post-coordinates.md", + "status": "added" + } + ] + }, + { + "pr": 882, + "title": "feat(reports): leftover-map item coordinates on leftover-map pair leftover-map criterion independently of leftover-map pair leftover-map post leftover-map person coordinates (v2.97.0)", + "head": "094d1a0c8bcfd4b351f9665c47a84c510cbab94d", + "base": "feat/leftover-map-list-post-coordinates-v2960", + "base_sha": "167888d669ba1b44c7dd0209ab26c9be9f19bf93", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 4, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0267-leftover-map-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0339-leftover-map-list-post-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0340-leftover-map-list-criterion-coordinates.md", + "status": "added" + } + ] + }, + { + "pr": 881, + "title": "feat(reports): leftover-map person coordinates on leftover-map pair leftover-map post independently of leftover-map pair leftover-map criterion leftover-map item coordinates (v2.96.0)", + "head": "167888d669ba1b44c7dd0209ab26c9be9f19bf93", + "base": "feat/leftover-map-plot-post-coordinates-v2950", + "base_sha": "c69459a3597a8a8af618417ce2c2a57a3114930b", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 3, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0267-leftover-map-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0268-leftover-map-graphic-display.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-graphic.md", + "status": "modified" + }, + { + "path": "docs/adr/0334-leftover-map-axis-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0337-leftover-map-compare-plot-post-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0338-leftover-map-plot-post-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0339-leftover-map-list-post-coordinates.md", + "status": "added" + } + ] + }, + { + "pr": 880, + "title": "feat(reports): leftover-map person coordinates on leftover-map graphic leftover-map post markers independently of leftover-map comparison graphic leftover-map post markers (v2.95.0)", + "head": "c69459a3597a8a8af618417ce2c2a57a3114930b", + "base": "feat/leftover-map-compare-plot-post-coordinates-v2940", + "base_sha": "d9972c260b1864e0b6391cbf050686e0bdd73359", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0267-leftover-map-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0268-leftover-map-graphic-display.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-graphic.md", + "status": "modified" + }, + { + "path": "docs/adr/0334-leftover-map-axis-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0337-leftover-map-compare-plot-post-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0338-leftover-map-plot-post-coordinates.md", + "status": "added" + } + ] + }, + { + "pr": 879, + "title": "feat(reports): leftover-map person coordinates on leftover-map comparison graphic leftover-map post markers independently of leftover-map criterion leftover-map item coordinates (v2.94.0)", + "head": "d9972c260b1864e0b6391cbf050686e0bdd73359", + "base": "feat/leftover-map-compare-plot-criterion-coordinates-v2930", + "base_sha": "617b97126a14337a4848f2b5663ada381ae693c0", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 3, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0267-leftover-map-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0268-leftover-map-graphic-display.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-graphic.md", + "status": "modified" + }, + { + "path": "docs/adr/0334-leftover-map-axis-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0336-leftover-map-compare-plot-criterion-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0337-leftover-map-compare-plot-post-coordinates.md", + "status": "added" + } + ] + }, + { + "pr": 878, + "title": "feat(reports): leftover-map item coordinates on leftover-map comparison graphic leftover-map criterion markers independently of leftover-map post \u03be markers (v2.93.0)", + "head": "617b97126a14337a4848f2b5663ada381ae693c0", + "base": "feat/leftover-map-plot-criterion-coordinates-v2920", + "base_sha": "89ed56b17acec187fd8e5f756c6b9a6a8f00438c", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0267-leftover-map-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0268-leftover-map-graphic-display.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-graphic.md", + "status": "modified" + }, + { + "path": "docs/adr/0334-leftover-map-axis-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0335-leftover-map-plot-criterion-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0336-leftover-map-compare-plot-criterion-coordinates.md", + "status": "added" + } + ] + }, + { + "pr": 877, + "title": "feat(reports): leftover-map origin on leftover-map comparison graphic leftover-map axis ticks independently of leftover-map axis share and leftover-map singular values (v2.92.0)", + "head": "86b8eaab48a4b47610d539bb941b97eb24b7e951", + "base": "feat/leftover-map-axis-tick-share-badge-v2910", + "base_sha": "d19f1fdc18cf16bac0e80bf6ae4257b831a4a619", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0335-leftover-map-compare-plot-tick-origin-badge.md", + "status": "added" + } + ] + }, + { + "pr": 876, + "title": "feat(reports): leftover-map item coordinates on leftover-map graphic leftover-map criterion markers independently of leftover-map post \u03be markers (v2.92.0)", + "head": "89ed56b17acec187fd8e5f756c6b9a6a8f00438c", + "base": "feat/leftover-map-axis-tick-share-badge-v2910", + "base_sha": "d19f1fdc18cf16bac0e80bf6ae4257b831a4a619", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0267-leftover-map-coordinates.md", + "status": "modified" + }, + { + "path": "docs/adr/0268-leftover-map-graphic-display.md", + "status": "modified" + }, + { + "path": "docs/adr/0334-leftover-map-axis-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0335-leftover-map-plot-criterion-coordinates.md", + "status": "added" + } + ] + }, + { + "pr": 875, + "title": "feat(reports): leftover-map axis share on leftover-axis ticks independently of leftover-map singular values (v2.91.0)", + "head": "d19f1fdc18cf16bac0e80bf6ae4257b831a4a619", + "base": "feat/leftover-map-compare-axis-tick-share-badge-v2900", + "base_sha": "ba58c21a92966fe098988e528020d5528978d06c", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0330-leftover-map-axis-tick-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0331-leftover-map-compare-plot-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0332-leftover-map-plot-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0333-leftover-map-compare-axis-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0334-leftover-map-axis-tick-share-badge.md", + "status": "added" + } + ] + }, + { + "pr": 874, + "title": "feat(reports): leftover-map axis share on leftover-map comparison leftover-axis ticks independently of leftover-map singular values (v2.90.0)", + "head": "ba58c21a92966fe098988e528020d5528978d06c", + "base": "feat/leftover-map-plot-tick-share-badge-v2890", + "base_sha": "923bcfe8a9146286ec3098adb784f55ffe32a78e", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0329-leftover-map-compare-axis-tick-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0330-leftover-map-axis-tick-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0331-leftover-map-compare-plot-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0332-leftover-map-plot-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0333-leftover-map-compare-axis-tick-share-badge.md", + "status": "added" + } + ] + }, + { + "pr": 873, + "title": "feat(reports): leftover-map axis share on leftover-map graphic leftover-map axis ticks independently of leftover-map singular values (v2.89.0)", + "head": "923bcfe8a9146286ec3098adb784f55ffe32a78e", + "base": "feat/leftover-map-compare-plot-tick-share-badge-v2880", + "base_sha": "7bdc562b222ab7681ff6b929a7b3fb2cd8068a3c", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 3, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0320-leftover-map-compare-plot-ticks.md", + "status": "modified" + }, + { + "path": "docs/adr/0324-leftover-map-plot-axis-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0327-leftover-map-plot-tick-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0328-leftover-map-compare-plot-tick-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0329-leftover-map-compare-axis-tick-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0330-leftover-map-axis-tick-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0331-leftover-map-compare-plot-tick-share-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0332-leftover-map-plot-tick-share-badge.md", + "status": "added" + } + ] + }, + { + "pr": 872, + "title": "feat(reports): leftover-map axis share on leftover-map comparison graphic leftover-map axis ticks independently of leftover-map singular values (v2.88.0)", + "head": "7bdc562b222ab7681ff6b929a7b3fb2cd8068a3c", + "base": "feat/leftover-map-axis-tick-badge-v2870", + "base_sha": "e9e4c2a622219bfbddfe71c74b14483f7b36aa5c", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0320-leftover-map-compare-plot-ticks.md", + "status": "modified" + }, + { + "path": "docs/adr/0326-leftover-map-compare-plot-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0327-leftover-map-plot-tick-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0328-leftover-map-compare-plot-tick-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0329-leftover-map-compare-axis-tick-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0330-leftover-map-axis-tick-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0331-leftover-map-compare-plot-tick-share-badge.md", + "status": "added" + } + ] + }, + { + "pr": 871, + "title": "feat(reports): leftover-map singular values on leftover-axis ticks independently of leftover-map axis share (v2.87.0)", + "head": "e9e4c2a622219bfbddfe71c74b14483f7b36aa5c", + "base": "feat/leftover-map-compare-axis-tick-badge-v2860", + "base_sha": "b086d97675586ee83f5478d7b4e3bf84b0a5da8c", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0329-leftover-map-compare-axis-tick-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0330-leftover-map-axis-tick-badge.md", + "status": "added" + } + ] + }, + { + "pr": 870, + "title": "feat(reports): leftover-map singular values on leftover-map comparison leftover-axis ticks independently of leftover-map axis share (v2.86.0)", + "head": "b086d97675586ee83f5478d7b4e3bf84b0a5da8c", + "base": "feat/leftover-map-compare-plot-tick-axis-badge-v2850", + "base_sha": "98a29e4adf0daad8bd30c945e41d45922051312d", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0328-leftover-map-compare-plot-tick-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0329-leftover-map-compare-axis-tick-badge.md", + "status": "added" + } + ] + }, + { + "pr": 869, + "title": "feat(reports): leftover-map singular values on leftover-map comparison graphic leftover-map axis ticks independently of leftover-map axis share (v2.85.0)", + "head": "98a29e4adf0daad8bd30c945e41d45922051312d", + "base": "feat/leftover-map-plot-tick-axis-badge-v2840", + "base_sha": "5218a5c0e6821451efdfac0c1286ef7273081af7", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0320-leftover-map-compare-plot-ticks.md", + "status": "modified" + }, + { + "path": "docs/adr/0326-leftover-map-compare-plot-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0327-leftover-map-plot-tick-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0328-leftover-map-compare-plot-tick-axis-badge.md", + "status": "added" + } + ] + }, + { + "pr": 868, + "title": "feat(reports): leftover-map singular values on leftover-map graphic leftover-map axis ticks independently of leftover-map axis share (v2.84.0)", + "head": "5218a5c0e6821451efdfac0c1286ef7273081af7", + "base": "feat/leftover-map-compare-plot-axis-badge-v2830", + "base_sha": "cf7bb55db1ba098e4ab264605634a686e4664d56", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0326-leftover-map-compare-plot-axis-badge.md", + "status": "modified" + }, + { + "path": "docs/adr/0327-leftover-map-plot-tick-axis-badge.md", + "status": "added" + } + ] + }, + { + "pr": 867, + "title": "feat(reports): leftover-map comparison graphic leftover-map axis leftover-map singular values as leftoverMapComparePlotAxisBadge (v2.83.0)", + "head": "cf7bb55db1ba098e4ab264605634a686e4664d56", + "base": "feat/leftover-map-axis-singular-only-v2820", + "base_sha": "593b8d8246c73226e224d2a9d251668649cbb54f", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0321-leftover-map-compare-plot-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0322-leftover-map-axis-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0323-leftover-map-compare-axis-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0324-leftover-map-plot-axis-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0325-leftover-map-axis-singular-only.md", + "status": "modified" + }, + { + "path": "docs/adr/0326-leftover-map-compare-plot-axis-badge.md", + "status": "added" + } + ] + }, + { + "pr": 866, + "title": "feat(reports): leftover-map singular values on leftover-axis report badges independently of leftover-map axis share (v2.82.0)", + "head": "593b8d8246c73226e224d2a9d251668649cbb54f", + "base": "feat/leftover-map-plot-axis-singular-v2810", + "base_sha": "a3613acf8cafac056850ec7ebc45f6d77f77a074", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0322-leftover-map-axis-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0323-leftover-map-compare-axis-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0324-leftover-map-plot-axis-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0325-leftover-map-axis-singular-only.md", + "status": "added" + } + ] + }, + { + "pr": 865, + "title": "feat(reports): leftover-map singular values on leftover-map graphic-display axes (v2.81.0)", + "head": "a3613acf8cafac056850ec7ebc45f6d77f77a074", + "base": "feat/leftover-map-compare-axis-singular-v2800", + "base_sha": "52b3597e5c6b825f988a9c8a7c68ae1653535982", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0322-leftover-map-axis-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0323-leftover-map-compare-axis-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0324-leftover-map-plot-axis-singular.md", + "status": "added" + } + ] + }, + { + "pr": 863, + "title": "feat(reports): leftover-map singular values on comparison leftover-axis badges (v2.80.0)", + "head": "52b3597e5c6b825f988a9c8a7c68ae1653535982", + "base": "feat/leftover-map-axis-singular-v2790", + "base_sha": "f24b664ce88bb2b3898fcaa0fd0ee7f69c5e12f7", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0322-leftover-map-axis-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0323-leftover-map-compare-axis-singular.md", + "status": "added" + } + ] + }, + { + "pr": 862, + "title": "feat(reports): leftover-map singular values on leftover-axis report badges (v2.79.0)", + "head": "f24b664ce88bb2b3898fcaa0fd0ee7f69c5e12f7", + "base": "feat/leftover-map-compare-plot-singular-v2780", + "base_sha": "3aac452eef781f3c1a5da258cd1c0c548e4930e6", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0321-leftover-map-compare-plot-singular.md", + "status": "modified" + }, + { + "path": "docs/adr/0322-leftover-map-axis-singular.md", + "status": "added" + } + ] + }, + { + "pr": 861, + "title": "feat(reports): leftover-map singular values on grouping comparison graphic (v2.78.0)", + "head": "3aac452eef781f3c1a5da258cd1c0c548e4930e6", + "base": "feat/leftover-map-compare-plot-ticks-v2770", + "base_sha": "40fa5bdbfb9223a7ca89fccea47451a419d81048", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 3, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0320-leftover-map-compare-plot-ticks.md", + "status": "modified" + }, + { + "path": "docs/adr/0321-leftover-map-compare-plot-singular.md", + "status": "added" + } + ] + }, + { + "pr": 860, + "title": "feat(reports): leftover-map coordinate ticks on grouping comparison graphic (v2.77.0)", + "head": "40fa5bdbfb9223a7ca89fccea47451a419d81048", + "base": "feat/leftover-map-compare-plot-distance-v2760", + "base_sha": "9ba8535327bb2d42d5305d84017e6cd08a110c68", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 4, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0319-leftover-map-compare-plot-distance.md", + "status": "modified" + }, + { + "path": "docs/adr/0320-leftover-map-compare-plot-ticks.md", + "status": "added" + } + ] + }, + { + "pr": 859, + "title": "feat(reports): leftover-map distance on grouping comparison graphic (v2.76.0)", + "head": "9ba8535327bb2d42d5305d84017e6cd08a110c68", + "base": "feat/leftover-map-compare-plot-rank-v2750", + "base_sha": "4b9184fd83f6749e25384d7bcf5d9d7721437b77", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0318-leftover-map-compare-plot-rank.md", + "status": "modified" + }, + { + "path": "docs/adr/0319-leftover-map-compare-plot-distance.md", + "status": "added" + } + ] + }, + { + "pr": 858, + "title": "feat(reports): leftover-map rank on grouping comparison graphic (v2.75.0)", + "head": "4b9184fd83f6749e25384d7bcf5d9d7721437b77", + "base": "feat/leftover-map-compare-plot-expected-v2740", + "base_sha": "ade9ed5cc2f0530eb62d2d473d14d2ffb41eddba", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0315-leftover-map-compare-plot-residual.md", + "status": "modified" + }, + { + "path": "docs/adr/0316-leftover-map-compare-plot-observed.md", + "status": "added" + }, + { + "path": "docs/adr/0317-leftover-map-compare-plot-expected.md", + "status": "added" + }, + { + "path": "docs/adr/0318-leftover-map-compare-plot-rank.md", + "status": "added" + } + ] + }, + { + "pr": 857, + "title": "feat(reports): leftover expected on grouping comparison graphic (v2.74.0)", + "head": "ade9ed5cc2f0530eb62d2d473d14d2ffb41eddba", + "base": "feat/leftover-map-compare-plot-observed-v2730", + "base_sha": "cf3b6d4195f2ccb5fba5b8d3359f018c8f26332d", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0279-leftover-map-segment-expected.md", + "status": "modified" + }, + { + "path": "docs/adr/0300-leftover-map-compare-expected.md", + "status": "modified" + }, + { + "path": "docs/adr/0316-leftover-map-compare-plot-observed.md", + "status": "modified" + }, + { + "path": "docs/adr/0317-leftover-map-compare-plot-expected.md", + "status": "added" + } + ] + }, + { + "pr": 856, + "title": "feat(reports): leftover observed on grouping comparison graphic (v2.73.0)", + "head": "cf3b6d4195f2ccb5fba5b8d3359f018c8f26332d", + "base": "feat/leftover-map-compare-plot-residual-v2720", + "base_sha": "1087b16f2dba743bc0d1d4e08ff50811b5845393", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0278-leftover-map-segment-observed.md", + "status": "modified" + }, + { + "path": "docs/adr/0299-leftover-map-compare-observed.md", + "status": "modified" + }, + { + "path": "docs/adr/0315-leftover-map-compare-plot-residual.md", + "status": "modified" + }, + { + "path": "docs/adr/0316-leftover-map-compare-plot-observed.md", + "status": "added" + } + ] + }, + { + "pr": 855, + "title": "feat(reports): leftover residual on grouping comparison graphic (v2.72.0)", + "head": "1087b16f2dba743bc0d1d4e08ff50811b5845393", + "base": "feat/leftover-map-compare-plot-unexplained-leftover-v2710", + "base_sha": "935cdea99c7c53ec7e99e4f455cd0653e34f4e30", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0277-leftover-map-segment-residual.md", + "status": "modified" + }, + { + "path": "docs/adr/0298-leftover-map-compare-residual.md", + "status": "modified" + }, + { + "path": "docs/adr/0314-leftover-map-compare-plot-unexplained-leftover.md", + "status": "modified" + }, + { + "path": "docs/adr/0315-leftover-map-compare-plot-residual.md", + "status": "added" + } + ] + }, + { + "pr": 854, + "title": "feat(reports): leftover-map unexplained leftover on grouping comparison graphic (v2.71.0)", + "head": "935cdea99c7c53ec7e99e4f455cd0653e34f4e30", + "base": "feat/leftover-map-compare-plot-cross-share-v2700", + "base_sha": "c4f79bc9ba4bc23317c8aa184aecd74eb1971704", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0276-leftover-map-segment-unexplained-leftover.md", + "status": "modified" + }, + { + "path": "docs/adr/0297-leftover-map-compare-unexplained.md", + "status": "modified" + }, + { + "path": "docs/adr/0313-leftover-map-compare-plot-cross-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0314-leftover-map-compare-plot-unexplained-leftover.md", + "status": "added" + } + ] + }, + { + "pr": 853, + "title": "feat(reports): leftover-map cross share on grouping comparison graphic (v2.70.0)", + "head": "c4f79bc9ba4bc23317c8aa184aecd74eb1971704", + "base": "feat/leftover-map-compare-plot-unexplained-share-v2690", + "base_sha": "2c34896b5fcf8f306103d28a610aced0a9d964b4", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0275-leftover-map-segment-cross-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0296-leftover-map-compare-cross-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0312-leftover-map-compare-plot-unexplained-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0313-leftover-map-compare-plot-cross-share.md", + "status": "added" + } + ] + }, + { + "pr": 852, + "title": "feat(reports): leftover-map unexplained leftover share on grouping comparison graphic (v2.69.0)", + "head": "2c34896b5fcf8f306103d28a610aced0a9d964b4", + "base": "feat/leftover-map-compare-plot-explained-share-v2680", + "base_sha": "2d6e8e778e2abb491b3a3c0a8b085c8230c9def4", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0274-leftover-map-segment-unexplained-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0295-leftover-map-compare-unexplained-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0311-leftover-map-compare-plot-explained-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0312-leftover-map-compare-plot-unexplained-share.md", + "status": "added" + } + ] + }, + { + "pr": 851, + "title": "feat(reports): leftover-map explained leftover share on grouping comparison graphic (v2.68.0)", + "head": "2d6e8e778e2abb491b3a3c0a8b085c8230c9def4", + "base": "feat/leftover-map-compare-plot-reconstruction-v2670", + "base_sha": "85451d87c9ddb4559a13366b1352af1bea7aafa0", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0273-leftover-map-segment-explained-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0294-leftover-map-compare-explained-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0310-leftover-map-compare-plot-reconstruction.md", + "status": "modified" + }, + { + "path": "docs/adr/0311-leftover-map-compare-plot-explained-share.md", + "status": "added" + } + ] + }, + { + "pr": 850, + "title": "feat(reports): leftover-map reconstruction on grouping comparison graphic (v2.67.0)", + "head": "85451d87c9ddb4559a13366b1352af1bea7aafa0", + "base": "feat/leftover-map-compare-plot-incomplete-item-v2660", + "base_sha": "43ce1936bfc3b035e591898ad5141a1b81cc526c", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0272-leftover-map-segment-reconstruction.md", + "status": "modified" + }, + { + "path": "docs/adr/0293-leftover-map-compare-reconstruction.md", + "status": "modified" + }, + { + "path": "docs/adr/0309-leftover-map-compare-plot-incomplete-item.md", + "status": "modified" + }, + { + "path": "docs/adr/0310-leftover-map-compare-plot-reconstruction.md", + "status": "added" + } + ] + }, + { + "pr": 849, + "title": "feat(reports): leftover-map incomplete items on grouping comparison graphic (v2.66.0)", + "head": "43ce1936bfc3b035e591898ad5141a1b81cc526c", + "base": "feat/leftover-map-compare-plot-incomplete-post-v2650", + "base_sha": "6707725ecaeb47c33c8a55b0801c8156527c6f01", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 4, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0284-leftover-map-plot-incomplete-item.md", + "status": "modified" + }, + { + "path": "docs/adr/0292-leftover-map-compare-incomplete-item.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-graphic.md", + "status": "modified" + }, + { + "path": "docs/adr/0307-leftover-map-compare-plot-item-coverage.md", + "status": "modified" + }, + { + "path": "docs/adr/0308-leftover-map-compare-plot-incomplete-post.md", + "status": "modified" + }, + { + "path": "docs/adr/0309-leftover-map-compare-plot-incomplete-item.md", + "status": "added" + } + ] + }, + { + "pr": 848, + "title": "feat(reports): leftover-map incomplete posts on grouping comparison graphic (v2.65.0)", + "head": "6707725ecaeb47c33c8a55b0801c8156527c6f01", + "base": "feat/leftover-map-compare-plot-item-coverage-v2640", + "base_sha": "47797643dc5c3071a7bbe3970ab563755113aa5b", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0283-leftover-map-plot-incomplete.md", + "status": "modified" + }, + { + "path": "docs/adr/0291-leftover-map-compare-incomplete-post.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-graphic.md", + "status": "modified" + }, + { + "path": "docs/adr/0307-leftover-map-compare-plot-item-coverage.md", + "status": "modified" + }, + { + "path": "docs/adr/0308-leftover-map-compare-plot-incomplete-post.md", + "status": "added" + } + ] + }, + { + "pr": 847, + "title": "docs(prd): reconcile occupational authority identities", + "head": "9bb4f07a61a9275953974ef276a4af81940ba883", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0245-io-occupational-taxonomy-in-the-published-ontology.md", + "status": "modified" + } + ] + }, + { + "pr": 846, + "title": "feat(reports): leftover-map item coverage on grouping comparison graphic (v2.64.0)", + "head": "47797643dc5c3071a7bbe3970ab563755113aa5b", + "base": "feat/leftover-map-compare-plot-coverage-v2630", + "base_sha": "7c026df8d85f9eeae9850f44cdf5e1bc6d644aa7", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0282-leftover-map-plot-item-coverage.md", + "status": "modified" + }, + { + "path": "docs/adr/0290-leftover-map-compare-item-coverage.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-graphic.md", + "status": "modified" + }, + { + "path": "docs/adr/0306-leftover-map-compare-plot-coverage.md", + "status": "modified" + }, + { + "path": "docs/adr/0307-leftover-map-compare-plot-item-coverage.md", + "status": "added" + } + ] + }, + { + "pr": 845, + "title": "feat(reports): leftover-map coverage on grouping comparison graphic (v2.63.0)", + "head": "7c026df8d85f9eeae9850f44cdf5e1bc6d644aa7", + "base": "feat/leftover-map-compare-plot-axis-share-v2620", + "base_sha": "95538f9980dcba70a6d6d174500d00c7af01df6c", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0281-leftover-map-plot-coverage.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-graphic.md", + "status": "modified" + }, + { + "path": "docs/adr/0305-leftover-map-compare-plot-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0306-leftover-map-compare-plot-coverage.md", + "status": "added" + } + ] + }, + { + "pr": 844, + "title": "feat(reports): leftover-map axis share on grouping comparison graphic (v2.62.0)", + "head": "95538f9980dcba70a6d6d174500d00c7af01df6c", + "base": "feat/leftover-map-compare-graphic-v2610", + "base_sha": "ee467df2f0e322623d74e948144b78bc27964aff", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0269-leftover-map-axis-share-plot.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-graphic.md", + "status": "modified" + }, + { + "path": "docs/adr/0305-leftover-map-compare-plot-axis-share.md", + "status": "added" + } + ] + }, + { + "pr": 843, + "title": "feat(reports): leftover-map rank on grouping comparison leftover-pair payload (v2.62.0)", + "head": "2a5ab4d735a1240997150578b151c6b6492e2f43", + "base": "feat/leftover-map-compare-axis-share-v2610", + "base_sha": "12e40c93acb8473075199d8c8124b85b3d39adff", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0305-leftover-map-compare-rank-payload.md", + "status": "added" + } + ] + }, + { + "pr": 842, + "title": "feat(reports): leftover-map axis share on grouping comparison strip (v2.61.0)", + "head": "12e40c93acb8473075199d8c8124b85b3d39adff", + "base": "feat/leftover-map-compare-coordinates-payload-v2600", + "base_sha": "cbf994462ec787d4d3e7a2749f913f62fd9c96d0", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-axis-share.md", + "status": "added" + } + ] + }, + { + "pr": 841, + "title": "feat(reports): leftover-map graphic on grouping comparison strip (v2.61.0)", + "head": "ee467df2f0e322623d74e948144b78bc27964aff", + "base": "feat/leftover-map-compare-coordinates-payload-v2600", + "base_sha": "cbf994462ec787d4d3e7a2749f913f62fd9c96d0", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0268-leftover-map-graphic-display.md", + "status": "modified" + }, + { + "path": "docs/adr/0304-leftover-map-compare-graphic.md", + "status": "added" + } + ] + }, + { + "pr": 840, + "title": "feat(reports): leftover-map coordinates on grouping comparison payload (v2.60.0)", + "head": "cbf994462ec787d4d3e7a2749f913f62fd9c96d0", + "base": "feat/leftover-map-compare-coordinates-v2590", + "base_sha": "51bf33a83b8a03e0dc4de65422313e38c9d45a21", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 3, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0303-leftover-map-compare-coordinates-payload.md", + "status": "added" + } + ] + }, + { + "pr": 839, + "title": "feat(reports): leftover-map coordinates on grouping comparison strip (v2.59.0)", + "head": "51bf33a83b8a03e0dc4de65422313e38c9d45a21", + "base": "feat/leftover-map-compare-rank-v2580", + "base_sha": "6c7c66fc4a39dc140f85e93d87f899ddb0695229", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0302-leftover-map-compare-coordinates.md", + "status": "added" + } + ] + }, + { + "pr": 838, + "title": "feat(reports): leftover-map rank on grouping comparison strip (v2.58.0)", + "head": "6c7c66fc4a39dc140f85e93d87f899ddb0695229", + "base": "feat/leftover-map-compare-expected-v2570", + "base_sha": "e6638a8e1d93b89376c004c60db9f016e03f00e0", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0301-leftover-map-compare-rank.md", + "status": "added" + } + ] + }, + { + "pr": 837, + "title": "feat(reports): leftover expected on grouping comparison strip (v2.57.0)", + "head": "e6638a8e1d93b89376c004c60db9f016e03f00e0", + "base": "feat/leftover-map-compare-observed-v2560", + "base_sha": "ada0c86e86c0e1570269d3a5d1f9121624938797", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0300-leftover-map-compare-expected.md", + "status": "added" + } + ] + }, + { + "pr": 836, + "title": "feat(reports): leftover observed on grouping comparison strip (v2.56.0)", + "head": "ada0c86e86c0e1570269d3a5d1f9121624938797", + "base": "feat/leftover-map-compare-residual-v2550", + "base_sha": "a825c336d87a4f481717e45800630e4805ab15bc", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0299-leftover-map-compare-observed.md", + "status": "added" + } + ] + }, + { + "pr": 835, + "title": "feat(reports): leftover residual on grouping comparison strip (v2.55.0)", + "head": "a825c336d87a4f481717e45800630e4805ab15bc", + "base": "feat/leftover-map-compare-unexplained-v2540", + "base_sha": "18d89b498a58d68ec58100065d71664f2c691347", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0298-leftover-map-compare-residual.md", + "status": "added" + } + ] + }, + { + "pr": 833, + "title": "feat(reports): leftover-map unexplained leftover on grouping comparison strip (v2.54.0)", + "head": "18d89b498a58d68ec58100065d71664f2c691347", + "base": "feat/leftover-map-compare-cross-share-v2530", + "base_sha": "2cefc0b63436989210bca3204e7750e87edba662", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0297-leftover-map-compare-unexplained.md", + "status": "added" + } + ] + }, + { + "pr": 831, + "title": "feat(reports): leftover-map cross share on grouping comparison strip (v2.53.0)", + "head": "2cefc0b63436989210bca3204e7750e87edba662", + "base": "feat/leftover-map-compare-unexplained-share-v2520", + "base_sha": "4d82c2872cc27e08c0357cb4b7cf071ab81ab9d7", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0296-leftover-map-compare-cross-share.md", + "status": "added" + } + ] + }, + { + "pr": 829, + "title": "feat(reports): leftover-map unexplained leftover share on grouping comparison strip (v2.52.0)", + "head": "4d82c2872cc27e08c0357cb4b7cf071ab81ab9d7", + "base": "feat/leftover-map-compare-explained-share-v2510", + "base_sha": "ead81bd3f51005f083871dc0bd49148a42a351b2", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0295-leftover-map-compare-unexplained-share.md", + "status": "added" + } + ] + }, + { + "pr": 828, + "title": "feat(reports): leftover-map axis share on grouping comparison strip (v2.50.0)", + "head": "e79137611f0d3041ad836c21e49a95bf7ef1001e", + "base": "feat/leftover-map-compare-incomplete-item-v2490", + "base_sha": "bca6baabd917478bf4f6b688ec2755cde95e3575", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 3, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0293-leftover-map-compare-axis-share.md", + "status": "added" + } + ] + }, + { + "pr": 827, + "title": "feat(reports): leftover-map explained leftover share on grouping comparison strip (v2.51.0)", + "head": "ead81bd3f51005f083871dc0bd49148a42a351b2", + "base": "feat/leftover-map-compare-reconstruction-v2500", + "base_sha": "a4bf239f1cf07ea29bd49b28300f252be0ca7a19", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0294-leftover-map-compare-explained-share.md", + "status": "added" + } + ] + }, + { + "pr": 826, + "title": "feat(reports): leftover-map reconstruction on grouping comparison strip (v2.50.0)", + "head": "a4bf239f1cf07ea29bd49b28300f252be0ca7a19", + "base": "feat/leftover-map-compare-incomplete-item-v2490", + "base_sha": "bca6baabd917478bf4f6b688ec2755cde95e3575", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 3, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0293-leftover-map-compare-reconstruction.md", + "status": "added" + } + ] + }, + { + "pr": 825, + "title": "feat(reports): leftover-map incomplete item coverage on grouping comparison strip (v2.49.0)", + "head": "bca6baabd917478bf4f6b688ec2755cde95e3575", + "base": "feat/leftover-map-compare-incomplete-post-v2480", + "base_sha": "8b2ed956b2ba66e3aa2d149b701c242e3b016dd9", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0292-leftover-map-compare-incomplete-item.md", + "status": "added" + } + ] + }, + { + "pr": 824, + "title": "feat(reports): leftover-map incomplete post coverage on grouping comparison strip (v2.48.0)", + "head": "8b2ed956b2ba66e3aa2d149b701c242e3b016dd9", + "base": "feat/leftover-map-compare-item-coverage-v2470", + "base_sha": "6726353a13798c0d1566821de9885f1783ebe35f", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0291-leftover-map-compare-incomplete-post.md", + "status": "added" + } + ] + }, + { + "pr": 823, + "title": "feat(reports): leftover-map singular values on leftover-axis badges (v2.47.0)", + "head": "eb172c40d8ecd08f3e1c220cbf3117b488cddb30", + "base": "feat/leftover-map-plot-singular-v2460", + "base_sha": "b7222713a69acdf3d32bbce992001a2433946d21", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0290-leftover-map-axis-singular.md", + "status": "added" + } + ] + }, + { + "pr": 822, + "title": "feat(reports): leftover-map item complete-case coverage on grouping comparison strip (v2.47.0)", + "head": "6726353a13798c0d1566821de9885f1783ebe35f", + "base": "feat/leftover-map-compare-coverage-v2460", + "base_sha": "11a785533ba52e6b1c6854203818902e38736dc5", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0290-leftover-map-compare-item-coverage.md", + "status": "added" + } + ] + }, + { + "pr": 821, + "title": "feat(reports): leftover-map complete-case coverage on grouping comparison strip (v2.46.0)", + "head": "11a785533ba52e6b1c6854203818902e38736dc5", + "base": "feat/leftover-map-list-post-coverage-helper-v2450", + "base_sha": "a2c965511d26923bd878ec56d655fb8a0183c4d7", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0289-leftover-map-compare-coverage.md", + "status": "added" + } + ] + }, + { + "pr": 820, + "title": "feat(reports): leftover-map singular values on graphic axes (v2.46.0)", + "head": "b7222713a69acdf3d32bbce992001a2433946d21", + "base": "feat/leftover-map-list-post-coverage-helper-v2450", + "base_sha": "a2c965511d26923bd878ec56d655fb8a0183c4d7", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0269-leftover-map-axis-share-plot.md", + "status": "modified" + }, + { + "path": "docs/adr/0289-leftover-map-plot-singular.md", + "status": "added" + } + ] + }, + { + "pr": 819, + "title": "feat(reports): fail-close leftover-map pair-list post coverage (v2.45.0)", + "head": "a2c965511d26923bd878ec56d655fb8a0183c4d7", + "base": "feat/leftover-map-list-incomplete-item-v2440", + "base_sha": "aa3208959950637b52001457e7d4dfc1ef1764eb", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0288-leftover-map-list-post-coverage-helper.md", + "status": "added" + } + ] + }, + { + "pr": 818, + "title": "feat(reports): leftover-map incomplete item coverage on pair list (v2.44.0)", + "head": "aa3208959950637b52001457e7d4dfc1ef1764eb", + "base": "feat/leftover-map-list-incomplete-post-v2430", + "base_sha": "ef30930271a729044af2f690df04f0b89f751ffd", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0287-leftover-map-list-incomplete-item.md", + "status": "added" + } + ] + }, + { + "pr": 817, + "title": "feat(reports): leftover-map incomplete post coverage on pair list (v2.43.0)", + "head": "ef30930271a729044af2f690df04f0b89f751ffd", + "base": "feat/leftover-map-list-item-coverage-v2420", + "base_sha": "1e3d13ea5fa5744e8c0b9b7b4e8470fceb7630ea", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 2, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0286-leftover-map-list-incomplete-post.md", + "status": "added" + } + ] + }, + { + "pr": 816, + "title": "feat(reports): leftover-map item complete-case coverage on pair list (v2.42.0)", + "head": "1e3d13ea5fa5744e8c0b9b7b4e8470fceb7630ea", + "base": "feat/leftover-map-plot-incomplete-item-v2410", + "base_sha": "63092ded55a7c7d65b0f6586980b20d0d30f587d", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0285-leftover-map-list-item-coverage.md", + "status": "added" + } + ] + }, + { + "pr": 815, + "title": "feat(reports): leftover-map incomplete item coverage on graphic display (v2.41.0)", + "head": "63092ded55a7c7d65b0f6586980b20d0d30f587d", + "base": "feat/leftover-map-plot-incomplete-v2400", + "base_sha": "772928722264b001c669b580d19866ccd8b590e0", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 1, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0284-leftover-map-plot-incomplete-item.md", + "status": "added" + } + ] + }, + { + "pr": 814, + "title": "feat(reports): leftover-map incomplete post coverage on graphic display (v2.40.0)", + "head": "772928722264b001c669b580d19866ccd8b590e0", + "base": "feat/leftover-map-plot-item-coverage-v2390", + "base_sha": "de2a8a8b8fe275542f3350c649c7bca759b049a3", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0283-leftover-map-plot-incomplete.md", + "status": "added" + } + ] + }, + { + "pr": 813, + "title": "feat(reports): leftover-map item complete-case coverage on graphic display (v2.39.0)", + "head": "de2a8a8b8fe275542f3350c649c7bca759b049a3", + "base": "feat/leftover-map-plot-coverage-v2380", + "base_sha": "64964cb6c14703a9b4bd74bed16d43844d49d102", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0282-leftover-map-plot-item-coverage.md", + "status": "added" + } + ] + }, + { + "pr": 812, + "title": "feat(reports): leftover-map complete-case coverage on graphic display (v2.38.0)", + "head": "64964cb6c14703a9b4bd74bed16d43844d49d102", + "base": "feat/leftover-map-segment-rank-v2370", + "base_sha": "e626a1d0770208d6f821e06542091aa2ead87f25", + "draft": false, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0281-leftover-map-plot-coverage.md", + "status": "added" + } + ] + }, + { + "pr": 811, + "title": "feat(reports): leftover-map rank on pair segments (v2.37.0)", + "head": "1887be0de1133fd9bccc0aa169f71015d035a303", + "base": "feat/leftover-map-segment-explained-share-v2300", + "base_sha": "5a8afbd9099efae658ee3c2a9b02ceaa3b78022c", + "draft": true, + "review_decision": null, + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 4, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0048-persist-lsirm-leftover-pairs.md", + "status": "modified" + }, + { + "path": "docs/adr/0049-leftover-pair-report-ui.md", + "status": "modified" + }, + { + "path": "docs/adr/0182-leftover-map-unexplained.md", + "status": "modified" + }, + { + "path": "docs/adr/0185-leftover-map-cross-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0233-leftover-map-unexplained-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0268-leftover-map-graphic-display.md", + "status": "modified" + }, + { + "path": "docs/adr/0273-leftover-map-segment-explained-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0274-leftover-map-segment-unexplained-share.md", + "status": "added" + }, + { + "path": "docs/adr/0275-leftover-map-segment-cross-share.md", + "status": "added" + }, + { + "path": "docs/adr/0276-leftover-map-segment-unexplained-leftover.md", + "status": "added" + }, + { + "path": "docs/adr/0277-leftover-map-segment-residual.md", + "status": "added" + }, + { + "path": "docs/adr/0278-leftover-map-segment-observed.md", + "status": "added" + }, + { + "path": "docs/adr/0279-leftover-map-segment-expected.md", + "status": "added" + }, + { + "path": "docs/adr/0280-leftover-map-segment-rank.md", + "status": "added" + } + ] + }, + { + "pr": 808, + "title": "revert: undo #782 squash until independent APPROVE", + "head": "ef38ddc9cf4f81c6a30050fa2409d294779fbd93", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0048-persist-lsirm-leftover-pairs.md", + "status": "modified" + }, + { + "path": "docs/adr/0049-leftover-pair-report-ui.md", + "status": "modified" + }, + { + "path": "docs/adr/0148-leftover-map-axis-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0201-leftover-map-reconstruction.md", + "status": "modified" + }, + { + "path": "docs/adr/0266-leftover-map-explained-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0267-leftover-map-coordinates.md", + "status": "removed" + }, + { + "path": "docs/adr/0268-leftover-map-graphic-display.md", + "status": "removed" + }, + { + "path": "docs/adr/0269-leftover-map-axis-share-plot.md", + "status": "removed" + }, + { + "path": "docs/adr/0270-leftover-map-coordinate-ticks.md", + "status": "removed" + }, + { + "path": "docs/adr/0271-leftover-map-segment-distance.md", + "status": "removed" + }, + { + "path": "migrations/0245_report_leftover_map_coordinates.sql", + "status": "removed" + }, + { + "path": "migrations/rollback/0245_report_leftover_map_coordinates.sql", + "status": "removed" + } + ] + }, + { + "pr": 802, + "title": "feat(reports): leftover-map explained leftover share on pair segments (v2.30.0)", + "head": "32f1cda10a2a1a6cabd64a3ae6f59bd6f0b20fd6", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": false, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0048-persist-lsirm-leftover-pairs.md", + "status": "modified" + }, + { + "path": "docs/adr/0049-leftover-pair-report-ui.md", + "status": "modified" + }, + { + "path": "docs/adr/0201-leftover-map-reconstruction.md", + "status": "modified" + }, + { + "path": "docs/adr/0266-leftover-map-explained-share.md", + "status": "modified" + }, + { + "path": "docs/adr/0268-leftover-map-graphic-display.md", + "status": "modified" + }, + { + "path": "docs/adr/0271-leftover-map-segment-distance.md", + "status": "modified" + }, + { + "path": "docs/adr/0272-leftover-map-segment-reconstruction.md", + "status": "added" + }, + { + "path": "docs/adr/0273-leftover-map-segment-explained-share.md", + "status": "added" + } + ] + }, + { + "pr": 780, + "title": "fix(voice): distinguish carrying and evidence exports", + "head": "1d8fa267b059289e77301a09985dfac70a439814", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": false, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": true, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0252-temporal-primary-voice-history.md", + "status": "modified" + }, + { + "path": "docs/adr/0256-evidence-bearing-voice-combinations.md", + "status": "modified" + }, + { + "path": "docs/adr/README.md", + "status": "modified" + } + ] + }, + { + "pr": 774, + "title": "feat(dashboard): share actionable status notices", + "head": "0e4ba4e00a1578aba6f80fa25d7d779516b9af96", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [] + }, + { + "pr": 772, + "title": "test: lift ask_time_axis.py coverage 78% to 100%", + "head": "781ebb11a00b50bf1956ff3536eef46160271931", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [] + }, + { + "pr": 771, + "title": "test: lift fixtures.py 88% to 99% and vision_image.py 80% to 98%", + "head": "9a4dbfcd46d955cd758148cf55cfd5ee795b02cd", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [] + }, + { + "pr": 770, + "title": "feat(projects): complete timeline empty-state evidence", + "head": "101cd8acc1d510382ea928d4f6bb9c84b199349d", + "base": "main", + "base_sha": "83eba56149eb802cd63642c507c324c9976ec78e", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [] + }, + { + "pr": 702, + "title": "feat: enforce source semantic coverage evidence", + "head": "93e7b81d096ddfc1fda9080c9c6a9784cbfbcec2", + "base": "main", + "base_sha": "ff7431bd1851c03e737808d22c6a2d43968582f9", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0030-external-llm-gateway-environment.md", + "status": "modified" + }, + { + "path": "docs/adr/0208-externalize-local-mathematical-compute.md", + "status": "modified" + }, + { + "path": "docs/adr/0240-explicit-missing-body-import-boundary.md", + "status": "added" + }, + { + "path": "docs/adr/0241-source-classification-semantic-hints.md", + "status": "added" + }, + { + "path": "docs/adr/0242-private-content-semantic-coverage-audit.md", + "status": "added" + }, + { + "path": "docs/adr/0245-lineage-scoring-and-entity-resolution-owner-contract.md", + "status": "added" + }, + { + "path": "docs/adr/0246-export-source-ontology-coverage.md", + "status": "added" + }, + { + "path": "docs/adr/README.md", + "status": "modified" + } + ] + }, + { + "pr": 679, + "title": "feat(ask): persist public-claim envelopes for Global Ask verification", + "head": "135dfe7c4266c7a2098c622b7c9976eaf7304cdd", + "base": "main", + "base_sha": "ff7431bd1851c03e737808d22c6a2d43968582f9", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0215-global-ask-public-claim-verification.md", + "status": "modified" + }, + { + "path": "docs/adr/0229-public-claim-envelope.md", + "status": "added" + }, + { + "path": "docs/adr/README.md", + "status": "modified" + }, + { + "path": "migrations/0224_public_claim_envelope.sql", + "status": "added" + }, + { + "path": "migrations/rollback/0224_public_claim_envelope.sql", + "status": "added" + } + ] + }, + { + "pr": 672, + "title": "feat(ask): nominate persisted semantic evidence", + "head": "a3e87a89185fae03c5f18c79e2d97d12c73e8af9", + "base": "main", + "base_sha": "ff7431bd1851c03e737808d22c6a2d43968582f9", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0233-global-ask-semantic-candidate-nomination.md", + "status": "added" + }, + { + "path": "docs/adr/0234-global-ask-public-claim-verification.md", + "status": "added" + }, + { + "path": "docs/adr/README.md", + "status": "modified" + }, + { + "path": "migrations/0225_global_ask_semantic_candidate_search.sql", + "status": "added" + } + ] + }, + { + "pr": 667, + "title": "feat(ask): per-post Ask history stack with gap-baseline refresh", + "head": "0c0f4af572a94e63cc8ea4545e48f5eda32a389c", + "base": "main", + "base_sha": "ff7431bd1851c03e737808d22c6a2d43968582f9", + "draft": true, + "review_decision": "REVIEW_REQUIRED", + "auto_merge": false, + "current_head_approved_reviews": 0, + "unresolved_threads": 0, + "threads_truncated": false, + "authority_paths": [ + { + "path": "docs/adr/0017-authorized-analysis-run-create.md", + "status": "modified" + }, + { + "path": "docs/adr/0022-authorized-tepp-start.md", + "status": "modified" + }, + { + "path": "docs/adr/0050-seed-period-report-analysis-run.md", + "status": "modified" + }, + { + "path": "docs/adr/0132-tepp-topic-lineage-consumption-boundary.md", + "status": "modified" + }, + { + "path": "docs/adr/0207-repository-case-ontology-namespace-canonical.md", + "status": "modified" + }, + { + "path": "docs/adr/0218-current-contract-mcp-global-ask.md", + "status": "modified" + }, + { + "path": "docs/adr/0222-project-nodes-in-ontology-neighborhood.md", + "status": "modified" + }, + { + "path": "docs/adr/0230-pnpm-build-script-allowlist.md", + "status": "modified" + }, + { + "path": "docs/adr/0231-external-lineage-arithmetic-authority.md", + "status": "modified" + }, + { + "path": "docs/adr/0235-post-ask-conversation-history.md", + "status": "added" + }, + { + "path": "docs/adr/0236-legacy-ontology-namespace-publication.md", + "status": "added" + }, + { + "path": "docs/adr/0237-accelerator-runtime-service-boundary.md", + "status": "added" + }, + { + "path": "docs/adr/README.md", + "status": "modified" + }, + { + "path": "migrations/0223_post_ask_conversation_history.sql", + "status": "added" + }, + { + "path": "migrations/rollback/0223_post_ask_conversation_history.sql", + "status": "added" + } + ] + } + ], + "checks_observed_at_utc": "2026-09-05T09:08:30.883052+00:00", + "hosted_recheck": [ + { + "pr": 780, + "head": "1d8fa267b059289e77301a09985dfac70a439814", + "base": "83eba56149eb802cd63642c507c324c9976ec78e", + "state": "OPEN", + "auto_merge": true, + "merge_commit": null, + "checks": [ + { + "name": "Publish ontology to GitHub Pages", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Full test suite", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "queued", + "conclusion": null + }, + { + "name": "Validate ontology publication", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "queued", + "conclusion": null + }, + { + "name": "Frontend lint, test, build", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "queued", + "conclusion": null + }, + { + "name": "CodeQL", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "success" + }, + { + "name": "CodeQL compatibility analysis (python)", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "CodeQL compatibility analysis (actions)", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "CodeQL compatibility analysis (javascript-typescript)", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "Full test suite", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Frontend lint, test, build", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Publish ontology to GitHub Pages", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "gitleaks (secret scan)", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Validate ontology publication", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Detect changed scope", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "Detect changed scope", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "Detect CodeQL languages", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "success" + }, + { + "name": "cancel-closed-pr-runs", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "org-queue-sweep", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "cancel-superseded-pr-runs", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "Detect changed scope", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "Admit current pull request head", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "required-workflow-bootstrap", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "cancel-superseded-opencode-review-runs", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "scan-pr-queue", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "success" + }, + { + "name": "admit-current-head", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "Analyze (actions)", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Analyze (python)", + "head_sha": "1d8fa267b059289e77301a09985dfac70a439814", + "status": "completed", + "conclusion": "success" + } + ] + }, + { + "pr": 929, + "head": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "base": "83eba56149eb802cd63642c507c324c9976ec78e", + "state": "OPEN", + "auto_merge": true, + "merge_commit": null, + "checks": [ + { + "name": "admit-current-head", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "CodeQL", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "dependency-review", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "scorecard", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "trivy-fs", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "osv-scan", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "strix", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "Semgrep (multi-language SAST)", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "noema-review", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "CodeQL compatibility analysis (actions)", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "CodeQL compatibility analysis (python)", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "CodeQL compatibility analysis (javascript-typescript)", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "queued", + "conclusion": null + }, + { + "name": "Frontend lint, test, build", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Full test suite", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "gitleaks (secret scan)", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Detect changed scope", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Detect CodeQL languages", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Detect changed scope", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Publish ontology to GitHub Pages", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Registry, inference, coverage, PostgreSQL", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Validate ontology publication", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "required-workflow-bootstrap", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Detect changed scope", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "cancel-superseded-pr-runs", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "cancel-superseded-opencode-review-runs", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Admit current pull request head", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "cancel-closed-pr-runs", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "admit-current-head", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "scan-pr-queue", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Analyze (python)", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Analyze (actions)", + "head_sha": "2a8ed5d02f4a3082b346d923d754c1ff37ebff52", + "status": "completed", + "conclusion": "success" + } + ] + }, + { + "pr": 934, + "head": "3060dd7000791160c2bcc98351af129899ff32ff", + "base": "1d8fa267b059289e77301a09985dfac70a439814", + "state": "OPEN", + "auto_merge": false, + "merge_commit": null, + "checks": [ + { + "name": "Full test suite", + "head_sha": "3060dd7000791160c2bcc98351af129899ff32ff", + "status": "queued", + "conclusion": null + }, + { + "name": "Frontend lint, test, build", + "head_sha": "3060dd7000791160c2bcc98351af129899ff32ff", + "status": "queued", + "conclusion": null + } + ] + }, + { + "pr": 914, + "head": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "base": "83eba56149eb802cd63642c507c324c9976ec78e", + "state": "OPEN", + "auto_merge": true, + "merge_commit": null, + "checks": [ + { + "name": "Full test suite", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "Frontend lint, test, build", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "Frontend lint, test, build", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "gitleaks (secret scan)", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Full test suite", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Detect changed scope", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "Detect changed scope", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "Detect CodeQL languages", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "cancel-closed-pr-runs", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "cancel-superseded-opencode-review-runs", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "required-workflow-bootstrap", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "scan-pr-queue", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "cancel-superseded-pr-runs", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "admit-current-head", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "Detect changed scope", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "Admit current pull request head", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "Analyze (python)", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + }, + { + "name": "Analyze (actions)", + "head_sha": "64340c0a86f876f32d0a37ef17321f3d9b993818", + "status": "queued", + "conclusion": null + } + ] + }, + { + "pr": 911, + "head": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "base": "83eba56149eb802cd63642c507c324c9976ec78e", + "state": "OPEN", + "auto_merge": true, + "merge_commit": null, + "checks": [ + { + "name": "publish-manual-pr-evidence-status", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "coverage-source-tree", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "queued", + "conclusion": null + }, + { + "name": "Semgrep OSS", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "osv-scanner", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Scorecard", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Trivy", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "admit-current-head", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Semgrep (multi-language SAST)", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "osv-scan", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "scorecard", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "trivy-fs", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "dependency-review", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "failure" + }, + { + "name": "CodeQL compatibility analysis (javascript-typescript)", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "failure" + }, + { + "name": "CodeQL compatibility analysis (actions)", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "failure" + }, + { + "name": "CodeQL compatibility analysis (python)", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "failure" + }, + { + "name": "noema-review", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "failure" + }, + { + "name": "CodeQL", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "strix", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "failure" + }, + { + "name": "Frontend lint, test, build", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Full test suite", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "gitleaks (secret scan)", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Detect changed scope", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Detect CodeQL languages", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Detect changed scope", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "required-workflow-bootstrap", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Publish ontology to GitHub Pages", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "cancel-superseded-opencode-review-runs", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "cancel-superseded-pr-runs", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Registry, inference, coverage, PostgreSQL", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Admit current pull request head", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Validate ontology publication", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Detect changed scope", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "org-queue-sweep", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "cancel-closed-pr-runs", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "scan-pr-queue", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "admit-current-head", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Analyze (python)", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Analyze (actions)", + "head_sha": "5d40eed35a0b6e0d182397f8d02b29c38e9bdd17", + "status": "completed", + "conclusion": "success" + } + ] + }, + { + "pr": 907, + "head": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "base": "83eba56149eb802cd63642c507c324c9976ec78e", + "state": "OPEN", + "auto_merge": true, + "merge_commit": null, + "checks": [ + { + "name": "opencode-review", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "queued", + "conclusion": null + }, + { + "name": "coverage-evidence", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "publish-manual-pr-evidence-status", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "cancel-closed-pr-runs", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "admit-current-head", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "noema-review", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "failure" + }, + { + "name": "coverage-source-tree", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Trivy", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Scorecard", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Semgrep OSS", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "admit-current-head", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "strix", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "cancelled" + }, + { + "name": "CodeQL compatibility analysis (actions)", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "failure" + }, + { + "name": "CodeQL compatibility analysis (javascript-typescript)", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "failure" + }, + { + "name": "CodeQL compatibility analysis (python)", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "failure" + }, + { + "name": "osv-scan", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "dependency-review", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "scorecard", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "trivy-fs", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Semgrep (multi-language SAST)", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Full test suite", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Frontend lint, test, build", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "gitleaks (secret scan)", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Frontend lint, test, build", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Full test suite", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "Detect changed scope", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Detect changed scope", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Detect CodeQL languages", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "cancel-superseded-pr-runs", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Admit current pull request head", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Detect changed scope", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "cancel-superseded-opencode-review-runs", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "required-workflow-bootstrap", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "org-queue-sweep", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "skipped" + }, + { + "name": "scan-pr-queue", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Analyze (python)", + "head_sha": "847a15e73e69bfc768d517a83fa8706aecfafe7e", + "status": "completed", + "conclusion": "success" + } + ] + } + ] +} diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 70238eae5..cfaf400ab 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,8 +1,146 @@ # Product & Technical Gap Baseline -## Current bounded loop — 2026-09-05 - -This section supersedes every dated snapshot below. It records observations, +## Current bounded loop — 2026-09-05 09:03 UTC + +Protected `main` was `83eba56149eb802cd63642c507c324c9976ec78e`. +The tested implementation is `b49a68a288cd7babf1d80436180521d5e0c3b31d`, +stacked on #934 at `3060dd7000791160c2bcc98351af129899ff32ff`, whose parent +is #780 at `1d8fa267b059289e77301a09985dfac70a439814`. Evidence-only commits +after the implementation do not replace its tested identity. No protected +merge or deployed-release completion is claimed. + +### Authority, implementation, and chosen user gap + +The current LineageWeave PRD and ADR 0184/0246/0251/0256 were read, along with +remote ThreadWeave `docs/PRD.md`, RankWeave `ARCHITECTURE.md`, TEPP +`docs/product/prd-v0.4-approved.md`, contextual-orchestrator +`docs/product_planning.md`, and disksage's current design authority. GitHub +confirmed `ContextualWisdomLab/LineageWeave`, `RankWeave`, `ThreadWeave`, `TEPP`, +`contextual-orchestrator`, and lowercase `disksage`. PRD spelling/duplicate +requirement identities remain owned by #847/#807; no second repository is +inferred from case differences. ADR 0251 here owns I/O Psychology; the +reconciled Voice composition authority is ADR 0256, extending ADR 0246. + +The selected gap is a reproducible mismatch in an existing evidence export: +search removed an edge and its target from the visible neighborhood, but its +source's direct JSON-LD assertion survived. This is prioritized as an observed +evidence-integrity failure, without assigning unsupported scores to product +opportunities. Filtering now retains direct assertions only for retained typed +source/property/target triples, both before and after page accumulation. Node +metadata and authorized Voice derivations are preserved. There is no new API, +schema, release number, inference policy, arithmetic, or provider integration. +The W3C [RDF triple contract](https://www.w3.org/TR/rdf11-concepts/#section-triples) +and [JSON-LD node objects](https://www.w3.org/TR/json-ld11/#node-objects) explain +the projection; they do not establish stakeholder classifications or weights. + +Three new regressions failed before the repair and passed afterward. Related +frontend validation passed 43 tests, lint, TypeScript, and production build. +Backend validation passed 33 tests, including real Keycloak/JWKS authentication +and primary-Voice PostgreSQL API projection against a newly migrated synthetic +database. No DeprecationWarning was emitted; the existing build chunk-size +advisory was retained without suppression or speculative tuning. + +`FilteredExportEvidence` reuses the existing Storybook component and tokens. +Real Chromium search/download checks passed at 1440×1000 and 390×844: the +removed assertion is absent from the downloaded JSON-LD and the retained +assertion remains. Both document widths equal viewport widths. Visually +reviewed [desktop](screenshots/ontology-filter-export-20260905-desktop.png) and +[mobile](screenshots/ontology-filter-export-20260905-mobile.png) show the +retained relationship and the mobile table's contained horizontal scroll. +The first rendering attempt timed out; the subsequent completed render and +actual downloads are the evidence. This is synthetic Storybook plus a separate +authenticated API check, not authenticated deployed end-to-end acceptance. +Full additional-Voice, hidden-evidence, cutoff, and paged authenticated UI +acceptance therefore remains **unavailable**. + +### Live aggregates and descriptive load + +The official `lineageweave` PostgreSQL returned 43,189 source records and +43,189 Voice associations, all primary. The aggregate query that assumed an +`evidence_post_id` storage column failed and was corrected to the verified +count/primary columns; no schema repair or identifying output was performed. +These exact counts do not establish functional acceptance or a population +inference. No real records were sampled or exported. + +A synthetic authenticated k6 HTTP observation used 2 VUs for 10 seconds: +4 successful requests, 0 failed requests, 0.349 requests/second, p95 6414.11 ms, +maximum 6414.16 ms. Across 51 PostgreSQL samples, peak connections were 5, +active sessions 2, and lock waiters 0, including the observer. This is a short +observed workload, not an SLO, capacity estimate, or identified bottleneck. +The temporary API stopped and its synthetic database was removed. + +A separate official-service snapshot showed PostgreSQL 2.21% CPU / 198.8 MiB, +Valkey 0.21% / 643.1 MiB, Ask worker 0.20% / 109.1 MiB, and orchestrator 0.01% / +76.79 MiB. It is not a synchronized saturation trace. This read-only workload +invokes neither worker nor model work; worker/Valkey/gateway end-to-end +saturation and attribution of the latency remain **unavailable**. No pool, +queue, routing, or mathematical policy was changed without causal evidence. +Formal Compose services and volumes were preserved; no test containers were +created. Sequential Thinking and Memory MCP tools were not callable in this +session; local memory informed the verification procedure only. DeepWiki had +no index and Context7 returned quota exhaustion; neither is authority evidence. + +### Exact-head queue, reviews, and conflicts + +The [remote metadata snapshot](development-loop-20260905-filter.json) records +117 open PRs at 08:48:46 UTC: 91 drafts, 26 ready, zero current-head approved +reviews, and 105 unresolved threads within the first 100 threads per PR. +Authority paths were refreshed for changed heads; paths from the earlier +snapshot were reused only for identical immutable heads. These are bounded +queue observations, not a claim that all 105 findings were adjudicated. +The 16 open Issues remain proposed work, distinct from implemented acceptance. + +#780 retains normal squash auto-merge and has no confirmed merge SHA. #934 +remains stacked on it. No child was retargeted or merged into an unprotected +parent. In-progress runs belonged to open #929 and #911 at their exact heads; +both were preserved. No stale run was cancelled and no CI contract change was +needed for a manually cleared stall. + +#929's existing minimal quality fixes were already present at +`2a8ed5d02f4a3082b346d923d754c1ff37ebff52`; its rollback/race/HTTP suite passed +12 tests in a separate checkout. The remaining no-effect findings refer to an +awaited database rollback task and two Protocol signatures. The awaited task +has required completion/error semantics; ellipsis protocol bodies follow the +[Python typing specification](https://typing.python.org/en/latest/spec/protocol.html#defining-a-protocol). +The three threads were resolved after exact-head verification, and normal +squash auto-merge was re-enabled with a matching-head guard. No warning +suppression or redundant code rewrite was added. The primary +checkout's concurrent translation-ledger changes were preserved. + +Exact-head added-path comparison reconfirms ten ADR identifier collisions: +0355 (#920/#915), 0301 (#902/#838), 0300 (#899/#837), 0279 (#888/#811), +0335 (#877/#876), 0305 (#844/#843), 0304 (#842/#841), 0293 (#828/#826), +0290 (#823/#822), and 0289 (#821/#820). The six proposed release-title +collisions in the earlier snapshot remain unresolved. No distinct added +migration filenames share a numeric prefix in this snapshot; cross-branch SQL +replay and semantic compatibility are not thereby proven. API-file overlap +remains a review target, not proof of a conflict. Parent-first protected +merging, explicit authority reconciliation, then fresh child checks/reviews +are required before delivery. Final hosted recheck: #780 retains three queued checks and cancelled earlier +central runs; #929 has eleven queued checks and no failures; #934 has two +queued checks. #914 has fourteen queued checks. #911 still fails dependency +review (GitHub HTTP 403), Noema (HTTP 502), CodeQL dispatch admission, and +Strix (cause not established here). #907 still fails Noema (HTTP 502) and +CodeQL's missing terminal dispatch verdict. These are unresolved hosted gates, +not local-product test failures, and none was bypassed or suppressed. Normal +auto-merge is enabled on #780/#929/#914/#911/#907. No merge SHA exists for any +of those open PRs at the recheck. + +The new repair is draft #935, created after the 117-PR queue snapshot, at +`76fcd6207f549f8cbe710c8a2f8c87227f3712ee` before this evidence-only update. +Its parent is #934. Repository Tests were correctly Draft-skipped, which is +not hosted GREEN; this child cannot auto-merge into its unprotected parent. +Fresh protected-main checks and independent approval remain required after +parent-first delivery. Six documentation/Voice contract tests passed after +the new baseline content was added. + +The active rules require independent approval, +resolved review threads, central workflows, and no force push; no bypass or +self-approval was used. + +## Earlier bounded loop — 2026-09-05 07:25 UTC + +This historical section is superseded by the current snapshot above. It records observations, not a protected-release claim. Remote `main` was `83eba56149eb802cd63642c507c324c9976ec78e`. The implemented export repair is `05384255df15c3995dbc3cef149abd5d92afd40a`, a child of #780 at diff --git a/docs/screenshots/ontology-filter-export-20260905-desktop.png b/docs/screenshots/ontology-filter-export-20260905-desktop.png new file mode 100644 index 000000000..cab24dc55 Binary files /dev/null and b/docs/screenshots/ontology-filter-export-20260905-desktop.png differ diff --git a/docs/screenshots/ontology-filter-export-20260905-mobile.png b/docs/screenshots/ontology-filter-export-20260905-mobile.png new file mode 100644 index 000000000..7363c8537 Binary files /dev/null and b/docs/screenshots/ontology-filter-export-20260905-mobile.png differ diff --git a/docs/storybook-inventory.md b/docs/storybook-inventory.md index 62c5f9cf3..f48aa05b5 100644 --- a/docs/storybook-inventory.md +++ b/docs/storybook-inventory.md @@ -13,7 +13,7 @@ operator-facing control you can click before changing product CSS. | `Post/Connect perspective` | Choose one unassigned Voice and an explicit evidence state, then record the open post as its evidence. `Ready`, `Completed`, and `NarrowViewport` cover untouched, successful, and mobile states. | `VoiceAssignmentForm`, `admin-form`, `btn-primary` | | `Evidence/CitationChip` | Click a cited title to open that source post. | `--color-chip-border`, `--radius-chip`, `CitationChip` | | `Evidence/OrganizationAliasChip` | Click a cataloged org; the parenthetical is the unique corroborated SKOS companion. | `--color-chip-border`, `--radius-chip`, `OrganizationAliasChip` | -| `Evidence/OntologyExplorer` | Distinguish Event Lineage from typed ontology facts, inspect Post/Person/Organization/Team/Project shapes, token-backed secondary cues, and truth labels, then open authorized evidence. The named exact-values region supports keyboard scrolling; `LongLabelsAndEvidenceTable` proves complete labels wrap without character-count truncation, while `CombinedVoiceEvidence` covers primary-plus-additional Voice assignments and focuses the evidence action distinct from the carrying-Post action. Desktop, narrow, drawers, legend/filter, empty, truncated, partial, denied, stale, and rejected scenes cover ADR 0184/0222/0256 states. The audited combined-Voice renders are `docs/screenshots/voice-combination-export-desktop.png` and `docs/screenshots/voice-combination-export-mobile.png`. | `OntologyExplorer`, `ontologyLayout`, `--ontology-node-*-fill`, `--color-table-border` | +| `Evidence/OntologyExplorer` | Distinguish Event Lineage from typed ontology facts, inspect Post/Person/Organization/Team/Project shapes, token-backed secondary cues, and truth labels, then open authorized evidence. The named exact-values region supports keyboard scrolling; `LongLabelsAndEvidenceTable` proves complete labels wrap without character-count truncation, while `FilteredExportEvidence` exercises search and JSON-LD download parity for direct assertions and `CombinedVoiceEvidence` covers primary-plus-additional Voice assignments and focuses the evidence action distinct from the carrying-Post action. Desktop, narrow, drawers, legend/filter, empty, truncated, partial, denied, stale, and rejected scenes cover ADR 0184/0222/0256 states. The audited combined-Voice renders are `docs/screenshots/voice-combination-export-desktop.png` and `docs/screenshots/voice-combination-export-mobile.png`. | `OntologyExplorer`, `ontologyLayout`, `--ontology-node-*-fill`, `--color-table-border` | | `Evidence/OntologyExplorer` | Distinguish Event Lineage from typed ontology facts, inspect Post/Person/Organization/Team/Project/Work-evidence shapes, token-backed secondary cues, and truth labels, then open authorized evidence. The populated scene includes one assertion-backed occupational construct without a person-trait promotion. The named exact-values region supports keyboard scrolling; `LongLabelsAndEvidenceTable` proves complete labels wrap without character-count truncation. Desktop, narrow, drawers, legend/filter, empty, truncated, partial, denied, stale, and rejected scenes cover ADR 0184/0222/0255 states. | `OntologyExplorer`, `ontologyLayout`, `--ontology-node-*-fill`, `--color-table-border` | | `AnalysisRun/CutoffKnownBody` | Read the cutoff-known sentence, then compare it with the live body below. | `--color-accent-border`, `--space-panel-block`, `--radius-panel`, `CutoffKnownBody` | | `Analysis/LineageEntityPicker` | Choose which corp to reconstruct, then click Request a lineage reconstruction. | `--space-control-gap`, `--size-control-min`, `--radius-control`, `LineageEntityPicker` | diff --git a/frontend/src/components/OntologyExplorer.stories.tsx b/frontend/src/components/OntologyExplorer.stories.tsx index 5e192ff0f..106dcae76 100644 --- a/frontend/src/components/OntologyExplorer.stories.tsx +++ b/frontend/src/components/OntologyExplorer.stories.tsx @@ -320,6 +320,34 @@ type Story = StoryObj; export const DesktopNeighborhood: Story = {}; +export const FilteredExportEvidence: Story = { + args: { + neighborhood: { + ...demoNeighborhood, + nodes: demoNeighborhood.nodes.slice(0, 3), + edges: demoNeighborhood.edges.slice(0, 2), + exact_value_rows: demoNeighborhood.exact_value_rows.slice(0, 2), + jsonld: { + ...demoNeighborhood.jsonld, + "@graph": [ + ...demoNeighborhood.nodes.slice(0, 3).map((node) => ({ + "@id": `https://contextualwisdomlab.github.io/LineageWeave/ontology#node/${node.node_type_code}/${node.node_id}`, + "@type": node.ontology_class_iri, + })), + ...demoNeighborhood.edges.slice(0, 2).flatMap((edge) => { + const source = `https://contextualwisdomlab.github.io/LineageWeave/ontology#node/${edge.source_node_type_code}/${edge.source_node_id}`; + const target = `https://contextualwisdomlab.github.io/LineageWeave/ontology#node/${edge.target_node_type_code}/${edge.target_node_id}`; + return [ + { "@id": source, [edge.ontology_property_iri]: { "@id": target } }, + { "@id": `lw:edge/${edge.edge_id}` }, + ]; + }), + ], + }, + }, + }, +}; + export const CombinedVoiceEvidence: Story = { args: { neighborhood: combinedVoiceNeighborhood }, play: ({ canvasElement }) => { diff --git a/frontend/src/ontologyCsvSecurity.test.ts b/frontend/src/ontologyCsvSecurity.test.ts new file mode 100644 index 000000000..9a4437f34 --- /dev/null +++ b/frontend/src/ontologyCsvSecurity.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, it } from "vitest"; + +import type { OntologyNeighborhoodPayload } from "./api"; +import { neighborhoodCsv } from "./ontologyLayout"; + +function csvWithSourceLabel(sourceLabel: string): string { + const payload = { + exact_value_rows: [ + { + edge_id: "edge-1", + source_label: sourceLabel, + property_label: "relates to", + target_label: "Target", + truth_status_code: "truth_authoritative", + recorded_at: "2026-09-05T00:00:00Z", + ontology_property_iri: "https://example.test/ontology#relatesTo", + property_code: "relatesTo", + source_node_id: "source", + target_node_id: "target", + }, + ], + voice_assignments: [], + } as unknown as OntologyNeighborhoodPayload; + return neighborhoodCsv(payload); +} + +describe("ontology CSV spreadsheet safety", () => { + it.each([ + ["\t=1+1", "'\t=1+1"], + ["\r=1+1", "\"'\r=1+1\""], + ["\n=1+1", "\"'\n=1+1\""], + ["\u0000=1+1", "'\u0000=1+1"], + ["=1+1", "'=1+1"], + ["+1+1", "'+1+1"], + ["-1+1", "'-1+1"], + ["@SUM(A1:A2)", "'@SUM(A1:A2)"], + ])("neutralizes formula-triggering source label %j", (sourceLabel, escapedCell) => { + expect(csvWithSourceLabel(sourceLabel)).toContain(`edge-1,${escapedCell},relates to`); + }); +}); diff --git a/frontend/src/ontologyLayout.test.ts b/frontend/src/ontologyLayout.test.ts index ed8e3b0fa..07cf7132d 100644 --- a/frontend/src/ontologyLayout.test.ts +++ b/frontend/src/ontologyLayout.test.ts @@ -116,6 +116,59 @@ function payload(): OntologyNeighborhoodPayload { } describe("ontologyLayout", () => { + it.each([false, true])("removes filtered direct assertions before or after page accumulation: %s", (accumulated) => { + const source = payload(); + const postIri = `${ONTOLOGY_NAMESPACE}node/node_post/${POST_ID}`; + const personIri = `${ONTOLOGY_NAMESPACE}node/node_person/${PERSON_ID}`; + const corpIri = `${ONTOLOGY_NAMESPACE}node/node_corporate_entity/${CORP_ID}`; + const withAssertions = { + ...source, + jsonld: { "@graph": [ + { "@id": postIri, "rdfs:label": "Demo public post" }, + { "@id": postIri, [source.edges[0].ontology_property_iri]: { "@id": personIri } }, + { "@id": personIri, "rdfs:label": "Test Person" }, + { "@id": personIri, [source.edges[1].ontology_property_iri]: { "@id": corpIri } }, + { "@id": corpIri, "rdfs:label": "Demo Corp" }, + { "@id": `lw:edge/${source.edges[0].edge_id}` }, + { "@id": `lw:edge/${source.edges[1].edge_id}` }, + ] }, + }; + const input = accumulated ? accumulateNeighborhoodPages(withAssertions, withAssertions) : withAssertions; + const before = JSON.stringify(input); + const result = filterNeighborhood(input, "Demo public")!; + expect(result.edges).toEqual([source.edges[0]]); + expect(JSON.stringify(result.jsonld)).not.toContain(corpIri); + expect(JSON.stringify(result.jsonld)).not.toContain(source.edges[1].ontology_property_iri); + expect(JSON.stringify(result.jsonld)).toContain(personIri); + expect(JSON.stringify(result.jsonld)).toContain("Test Person"); + expect(JSON.stringify(input)).toBe(before); + }); + + it("filters targets by the retained edge even when both endpoints remain visible", () => { + const source = payload(); + const postIri = `${ONTOLOGY_NAMESPACE}node/node_post/${POST_ID}`; + const personIri = `${ONTOLOGY_NAMESPACE}node/node_person/${PERSON_ID}`; + const corpIri = `${ONTOLOGY_NAMESPACE}node/node_corporate_entity/${CORP_ID}`; + const relation = source.edges[0].ontology_property_iri; + const first = { ...source.edges[0], truth_status_code: "truth_authoritative" }; + const second = { ...source.edges[0], edge_id: "other", target_node_id: CORP_ID, + target_node_type_code: "node_corporate_entity" }; + const connector = { ...source.edges[1], truth_status_code: "truth_authoritative" }; + const result = filterNeighborhood({ + ...source, + edges: [first, second, connector], + jsonld: { "@graph": [{ "@id": postIri, + [relation]: [{ "@id": personIri }, { "@id": corpIri }], + "prov:wasDerivedFrom": { "@id": "https://example.test/authorized-evidence" }, + }] }, + }, "truth_authoritative")!; + expect(result.nodes).toHaveLength(3); + expect(result.jsonld["@graph"]).toEqual([{ "@id": postIri, + [relation]: [{ "@id": personIri }], + "prov:wasDerivedFrom": { "@id": "https://example.test/authorized-evidence" }, + }]); + }); + it("keeps evidence-bearing voice assignments in CSV, filters, and page accumulation", () => { const source = payload(); const assignment = { diff --git a/frontend/src/ontologyLayout.ts b/frontend/src/ontologyLayout.ts index 63575b030..7b1fc661f 100644 --- a/frontend/src/ontologyLayout.ts +++ b/frontend/src/ontologyLayout.ts @@ -182,9 +182,13 @@ export function neighborhoodCsv(payload: OntologyNeighborhoodPayload): string { return `${lines.join("\n")}\n`; } +const SPREADSHEET_FORMULA_PREFIX = /^[=+\-@\t\r\n\u0000\uFF1D\uFF0B\uFF0D\uFF20]/u; + function csvCell(value: string): string { - const safeValue = /^[=+\-@]/.test(value) ? `'${value}` : value; - if (/[",\n]/.test(safeValue)) { + // Spreadsheet formula parsers recognize control and locale-specific prefixes + // beyond ASCII =+-@, so neutralize the complete export boundary before quoting. + const safeValue = SPREADSHEET_FORMULA_PREFIX.test(value) ? `'${value}` : value; + if (/[",\r\n]/.test(safeValue)) { return `"${safeValue.replaceAll('"', '""')}"`; } return safeValue; @@ -263,6 +267,19 @@ export function filterNeighborhood( `${ONTOLOGY_NAMESPACE}voice-assignment/${assignment.post_id}/${assignment.voice_type_code}`, ]), ); + const visibleEdgeIds = new Set(edges.map((edge) => edge.edge_id)); + const directTargets = new Map>(); + for (const edge of payload.edges) { + const key = JSON.stringify([ + ontologyNodeId(edge.source_node_type_code, edge.source_node_id), + edge.ontology_property_iri, + ]); + const targets = directTargets.get(key) ?? new Set(); + if (visibleEdgeIds.has(edge.edge_id)) { + targets.add(ontologyNodeId(edge.target_node_type_code, edge.target_node_id)); + } + directTargets.set(key, targets); + } const graph = payload.jsonld["@graph"]; const jsonld = Array.isArray(graph) ? { @@ -274,7 +291,15 @@ export function filterNeighborhood( (visibleIds.has(item["@id"]) || visibleNodeIds.has(item["@id"]) || visibleVoiceIds.has(item["@id"])), - ), + ).map((item) => Object.fromEntries(Object.entries(item).flatMap(([key, value]) => { + const targets = directTargets.get(JSON.stringify([item["@id"], key])); + if (!targets) return [[key, value]]; + const values = (Array.isArray(value) ? value : [value]).filter((target) => + typeof target === "object" && target !== null && + typeof target["@id"] === "string" && targets.has(target["@id"]), + ); + return values.length ? [[key, Array.isArray(value) ? values : values[0]]] : []; + }))), } : payload.jsonld; return {