-
Notifications
You must be signed in to change notification settings - Fork 1
feat: open Calendar commitments onto Event Lineage (v2.14.0) #261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d3f5e61
af2b114
6a63852
8a291d7
2c0d2be
343301e
47d2102
159f2ce
e3f9fae
93cb898
2039785
c2e7ecd
6f7dcb3
ecb5722
b829464
611fa08
507021e
bf2cf37
cae9f69
6e336c5
14d62e2
cc01b4d
0e62d30
9f26564
4a05a91
bd1b4d2
848ff4c
a71b8a6
221cc94
9bb02fa
c1d340f
6c4d48d
8cd94b2
0ff8643
b141ffc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # 2.14.0 Opening a Calendar commitment focuses Event Lineage | ||
|
|
||
| Calendar names authorized commitments as current and to open one to read | ||
| Event Lineage. That open focuses the popup Event Lineage heading. Home-list | ||
| opens do not. No TEPP theta is invented. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # ADR 0094: Opening a Calendar commitment focuses Event Lineage | ||
|
|
||
| - Status: Accepted | ||
| - Date: 2026-08-19 | ||
|
|
||
| ## Context | ||
|
|
||
| Board Weekly VOC opens already focus Event Lineage (ADR 0093). Calendar is | ||
| the other buyer destination that opens a source post from an authorized | ||
| commitment. That open was a home-list open: the popup body appeared and | ||
| Event Lineage did not take focus. | ||
|
|
||
| ## Decision | ||
|
|
||
| Opening a commitment on Calendar is a `fromCalendar` open. That open reuses | ||
| the Event Lineage focus path used by report-member and Weekly VOC opens: | ||
|
|
||
| - Calendar names the next action: authorized commitments are current; open | ||
| a commitment to read Event Lineage. | ||
| - The popup Event Lineage heading takes focus. | ||
| - The popup names the opened post as current in Event Lineage and tells | ||
| the buyer to read Keyman and evaluation next. | ||
|
|
||
| A Board home-list open does not focus Event Lineage and does not add that | ||
| copy. A `?post=` deep link is still a home-list open. | ||
|
|
||
| No TEPP theta is invented. No cutoff body is invented (ADR 0016). Calendar | ||
| does not invent a CalDAV event (ADR 0038). | ||
|
|
||
| ## Consequences | ||
|
|
||
| - Calendar, Weekly VOC, and report-member opens share one focus contract. | ||
| - Closing the popup clears the Calendar open flag. |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 Info: Board-reused CalendarPanel keeps neutral home-list open The advanced-review-tools Was this helpful? React with 👍 or 👎 to provide feedback. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -883,6 +883,7 @@ function KeymanPanel({ | |
| focusTeam, | ||
| landFirstKeyman, | ||
| landFirstRelated, | ||
| landOnAsk, | ||
| afterList, | ||
| }: { | ||
| postId: string; | ||
|
|
@@ -897,6 +898,7 @@ function KeymanPanel({ | |
| focusTeam?: { teamId: string; teamName: string } | null; | ||
| landFirstKeyman?: boolean; | ||
| landFirstRelated?: boolean; | ||
| landOnAsk?: boolean; | ||
| afterList?: ReactNode; | ||
| }) { | ||
| const [related, setRelated] = useState<RelatedNode[] | null>(null); | ||
|
|
@@ -1004,13 +1006,13 @@ function KeymanPanel({ | |
| }, [accessToken, landFirstRelated, related]); | ||
|
|
||
| useEffect(() => { | ||
| if (!landFirstRelated || !landedRelatedName || landedRelated === null) { | ||
| if (!landFirstRelated || !landOnAsk || !landedRelatedName || landedRelated === null) { | ||
| return; | ||
| } | ||
| const heading = document.getElementById("post-ask"); | ||
|
Comment on lines
1006
to
1012
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔍 Ask auto-focus/scroll now restricted to report-member opens changes Weekly VOC behavior The new (Refers to this code) Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| heading?.focus(); | ||
| heading?.scrollIntoView?.({ block: "nearest" }); | ||
| }, [landFirstRelated, landedRelatedName, landedRelated]); | ||
| }, [landFirstRelated, landedRelatedName, landedRelated, landOnAsk]); | ||
|
|
||
| useEffect(() => { | ||
| if (!focusPerson) return; | ||
|
|
@@ -1709,6 +1711,7 @@ function PostDetailPopup({ | |
| liveBodyWarning, | ||
| knowledgeCutoff, | ||
| focusEventLineage, | ||
| focusAskOnLand, | ||
| onClose, | ||
| onSelectPost, | ||
| onSearch, | ||
|
|
@@ -1720,6 +1723,7 @@ function PostDetailPopup({ | |
| liveBodyWarning?: string | null; | ||
| knowledgeCutoff?: string | null; | ||
| focusEventLineage?: boolean; | ||
| focusAskOnLand?: boolean; | ||
| onClose: () => void; | ||
| onSelectPost?: (postId: string) => void; | ||
| onSearch?: (query: string) => void; | ||
|
|
@@ -2365,6 +2369,7 @@ function PostDetailPopup({ | |
| focusTeam={focusTeam} | ||
| landFirstKeyman | ||
| landFirstRelated | ||
| landOnAsk={focusAskOnLand} | ||
| afterList={ | ||
| <> | ||
| <EvaluationPanel | ||
|
|
@@ -2584,6 +2589,7 @@ type SelectPostOptions = { | |
| knowledgeCutoff?: string; | ||
| fromReportMember?: boolean; | ||
| fromWeeklyVoc?: boolean; | ||
| fromCalendar?: boolean; | ||
| /** Set when re-entering a post from a popstate (browser back/forward) so | ||
| * the handler doesn't push a duplicate history entry for a navigation | ||
| * the browser already performed. */ | ||
|
|
@@ -3168,9 +3174,13 @@ function RankingsPanel({ | |
| function CalendarPanel({ | ||
| accessToken, | ||
| onSelectPost, | ||
| namedNextAction = false, | ||
| focusEventLineageOnSelect = false, | ||
| }: { | ||
| accessToken: string; | ||
| onSelectPost: (postId: string) => void; | ||
| onSelectPost: (postId: string, options?: SelectPostOptions) => void; | ||
| namedNextAction?: boolean; | ||
| focusEventLineageOnSelect?: boolean; | ||
| }) { | ||
| const [calendar, setCalendar] = useState<CalendarResponse | null>(null); | ||
| const [error, setError] = useState<string | null>(null); | ||
|
|
@@ -3190,8 +3200,13 @@ function CalendarPanel({ | |
| const caldavNextAction = calendar.calendar_sources?.caldav_next_action; | ||
|
|
||
| return ( | ||
| <section className="popup-section lineage-home"> | ||
| <h2>{t("Calendar")}</h2> | ||
| <section className="popup-section lineage-home" aria-labelledby="calendar-title"> | ||
| <h2 id="calendar-title">{t("Calendar")}</h2> | ||
| {namedNextAction && commitments.length > 0 ? ( | ||
| <p className="board-next-action" role="status" aria-label={t("Next action")}> | ||
| {t("Authorized commitments are current. Open a commitment to read Event Lineage.")} | ||
| </p> | ||
| ) : null} | ||
| <section className="popup-section"> | ||
| <h3>{t("CalDAV events")}</h3> | ||
| {events.length === 0 ? ( | ||
|
|
@@ -3226,7 +3241,12 @@ function CalendarPanel({ | |
| <button | ||
| className="post-list-item" | ||
| aria-label={`${t("Open commitment for:")} ${entry.post_title}`} | ||
| onClick={() => onSelectPost(entry.post_id)} | ||
| onClick={() => | ||
| onSelectPost( | ||
| entry.post_id, | ||
| focusEventLineageOnSelect ? { fromCalendar: true } : undefined, | ||
| ) | ||
| } | ||
| > | ||
| <span className="ticket-title"> | ||
| {entry.commitment_summary ?? entry.ticket_title} | ||
|
|
@@ -3623,13 +3643,15 @@ function PostList({ | |
| accessToken, | ||
| showLabPanels = false, | ||
| postIdToOpen = null, | ||
| postOpenFromCalendar = false, | ||
| onPostOpened, | ||
| focusSearchRequest = 0, | ||
| onSearchFocusHandled, | ||
| }: { | ||
| accessToken: string; | ||
| showLabPanels?: boolean; | ||
| postIdToOpen?: string | null; | ||
| postOpenFromCalendar?: boolean; | ||
| onPostOpened?: () => void; | ||
| focusSearchRequest?: number; | ||
| onSearchFocusHandled?: () => void; | ||
|
|
@@ -3651,6 +3673,7 @@ function PostList({ | |
| const [landOnComparison, setLandOnComparison] = useState(false); | ||
| const [openedFromReportMember, setOpenedFromReportMember] = useState(false); | ||
| const [openedFromWeeklyVoc, setOpenedFromWeeklyVoc] = useState(false); | ||
| const [openedFromCalendar, setOpenedFromCalendar] = useState(false); | ||
| const [corporateEntities, setCorporateEntities] = useState<CorporateEntityRef[] | null>(null); | ||
| const [entitiesLoadError, setEntitiesLoadError] = useState<string | null>(null); | ||
| const [totalPosts, setTotalPosts] = useState(0); | ||
|
|
@@ -3724,6 +3747,7 @@ function PostList({ | |
| setOpenedCutoffIso(options?.knowledgeCutoff ?? null); | ||
| setOpenedFromReportMember(Boolean(options?.fromReportMember)); | ||
| setOpenedFromWeeklyVoc(Boolean(options?.fromWeeklyVoc)); | ||
| setOpenedFromCalendar(Boolean(options?.fromCalendar)); | ||
| if (!options?.fromPopState) { | ||
| const url = new URL(window.location.href); | ||
| if (url.searchParams.get("post") !== postId) { | ||
|
|
@@ -3735,9 +3759,9 @@ function PostList({ | |
|
|
||
| useEffect(() => { | ||
| if (!postIdToOpen) return; | ||
| selectPost(postIdToOpen); | ||
| selectPost(postIdToOpen, postOpenFromCalendar ? { fromCalendar: true } : undefined); | ||
| onPostOpened?.(); | ||
| }, [onPostOpened, postIdToOpen]); | ||
| }, [onPostOpened, postIdToOpen, postOpenFromCalendar]); | ||
|
|
||
| useEffect(() => { | ||
| function handlePopState() { | ||
|
|
@@ -3761,6 +3785,7 @@ function PostList({ | |
| setOpenedCutoffIso(null); | ||
| setOpenedFromReportMember(false); | ||
| setOpenedFromWeeklyVoc(false); | ||
| setOpenedFromCalendar(false); | ||
| const url = new URL(window.location.href); | ||
| if (url.searchParams.has("post")) { | ||
| url.searchParams.delete("post"); | ||
|
|
@@ -4249,7 +4274,8 @@ function PostList({ | |
| openedAfterCutoff ? analysisRunOpenedBodyWarning(openedCutoffIso) : null | ||
| } | ||
| knowledgeCutoff={openedAfterCutoff ? openedCutoffIso : null} | ||
| focusEventLineage={openedFromReportMember || openedFromWeeklyVoc} | ||
| focusEventLineage={openedFromReportMember || openedFromWeeklyVoc || openedFromCalendar} | ||
| focusAskOnLand={openedFromReportMember} | ||
| onClose={closeSelectedPost} | ||
| onSelectPost={selectPost} | ||
| onSearch={searchBoard} | ||
|
|
@@ -4808,6 +4834,7 @@ export default function App({ showLabPanels = false }: { showLabPanels?: boolean | |
| if (typeof window === "undefined") return null; | ||
| return new URLSearchParams(window.location.search).get("post"); | ||
| }); | ||
| const [postOpenFromCalendar, setPostOpenFromCalendar] = useState(false); | ||
| // Test-only compatibility for legacy analysis-panel coverage; this prop | ||
| // never forces the panels open outside Vitest. In a real build the | ||
| // advanced-review section (ADR 0037) is gated on PostList's own | ||
|
|
@@ -4999,7 +5026,11 @@ export default function App({ showLabPanels = false }: { showLabPanels?: boolean | |
| accessToken={accessToken} | ||
| showLabPanels={testOnlyLabPanels} | ||
| postIdToOpen={postToOpen} | ||
| onPostOpened={() => setPostToOpen(null)} | ||
| postOpenFromCalendar={postOpenFromCalendar} | ||
| onPostOpened={() => { | ||
| setPostToOpen(null); | ||
| setPostOpenFromCalendar(false); | ||
| }} | ||
| focusSearchRequest={searchFocusRequest} | ||
| onSearchFocusHandled={() => setSearchFocusRequest(0)} | ||
| /> | ||
|
|
@@ -5016,8 +5047,11 @@ export default function App({ showLabPanels = false }: { showLabPanels?: boolean | |
| {destination === "calendar" ? ( | ||
| <CalendarPanel | ||
| accessToken={accessToken} | ||
| namedNextAction | ||
| focusEventLineageOnSelect | ||
| onSelectPost={(postId) => { | ||
| setPostToOpen(postId); | ||
| setPostOpenFromCalendar(true); | ||
| changeDestination("board"); | ||
| }} | ||
| /> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 Info: ADR 0094 rename is clean; no dangling references to old internal-relation-evidence ADR
The old
docs/adr/0094-internal-relation-evidence.mdis renamed to0095and the new0094is the Calendar ADR. I searched the whole repo: every remainingADR 0094reference (AGENTS.md, CLAUDE.md, ARCHITECTURE.md, CHANGELOG.md) now points to the Calendar decision, andrelation_verification_ingestion.py,migrations/0028_internal_relation_evidence.sql, andtests/test_relation_verification_internal.pydo not cite the ADR by number, so the renumber introduces no dangling references.Was this helpful? React with 👍 or 👎 to provide feedback.