[{"data":1,"prerenderedAt":838},["ShallowReactive",2],{"$f2ytmpd9dwz5x8":3,"mdc-ph4wrt-key":15},{"release":4,"newer":10,"older":12,"page":14},{"tag":5,"name":5,"publishedAt":6,"url":7,"prerelease":8,"markdown":9},"v1.1.1","2026-09-30T19:03:27Z","https:\u002F\u002Fgithub.com\u002Fanhourtec\u002FBookYourPTO-SaaS\u002Freleases\u002Ftag\u002Fv1.1.1",false,"### Review cycles that actually run, 1:1s with a time and a calendar entry, and a clear answer to who sets performance up\r\n\r\nPerformance has been rebuilt around a simple split: a **review cycle** says when reviews fall\r\ndue and who they cover, a **1:1** is the conversation itself, and the two can be linked so a\r\nreview is something worked towards rather than an event that arrives.\r\n\r\nThe largest change is that review cycles now do something. A cycle was a name and a pair of\r\ndates: the scope section on the form was never saved, so a department-wide cycle came out\r\ncovering everyone, and every cycle ever created was stuck in Draft because nothing in the\r\nproduct could open it. Cycles now run on either a shared window or each employee's own hire\r\nanniversary, cover everyone or one department or a chosen list, and send reminders to the people\r\nresponsible for holding the review.\r\n\r\n1:1s gained a time, a duration and a place in the participants' real calendars, and a 1:1\r\narranged by an administrator now pairs the right two people — previously it paired the\r\nadministrator with whoever's profile they were standing on.\r\n\r\nAlongside those: performance is now something an organization runs for its people rather than\r\nsomething people set up for themselves, destructive actions ask before they act, and several\r\ndates that shifted a day west of UTC have been fixed.\r\n\r\n### Review cycles\r\n\r\n- **A cycle can follow each employee's hire date** — Annual meant two different things depending\r\n  on who set it up: a company-wide window, or a review on each person's own anniversary. One\r\n  pair of date columns could not express the second at all. A cycle now chooses between\r\n  **specific dates** — one window for everyone in scope — and **employee hire date**, measured\r\n  from each person's own start date with no shared window.\r\n\r\n- **A hire-date cycle is not only the one-year mark** — It says how far after the start date the\r\n  review falls and whether it recurs: every year on the anniversary, once N months in, or every\r\n  N months. Without that, a cycle named \"3 Months Probation\" would have reminded on the\r\n  employee's first anniversary. A 29 February start is reviewed on 28 February in years that\r\n  have no 29th, and a 31st is held to the last day of a shorter month rather than spilling into\r\n  the next one.\r\n\r\n  This does not replace the probation review on a profile, which keeps its own period, its\r\n  extension date and its own reminders.\r\n\r\n- **The Type field is gone** — Annual, Semi-annual, Quarterly, Probation and Custom were a label\r\n  no code ever read. It implied a schedule it did not set: \"Probation\" connected to none of the\r\n  probation machinery, and \"Custom\" offered nothing to customise. The schedule now says what the\r\n  cycle is, and the name says what to call it.\r\n\r\n- **The scope you choose is the scope that is saved** — The form had department and employee\r\n  pickers and the endpoint discarded every one of those fields, so an administrator could\r\n  configure a department-wide cycle, watch it save, and get a row covering the whole company.\r\n  There was no column to record a department in. Scope is now stored, the department is checked\r\n  against the caller's own organization, and the list shows how many people each cycle currently\r\n  covers, so a department that has been emptied does not read the same as one with thirty people\r\n  in it.\r\n\r\n- **A new cycle is running, not stuck in Draft** — The create endpoint ignored the status\r\n  entirely, so every cycle fell through to Draft, and no control anywhere could move it out. A\r\n  cycle is now created Active, and Status is a switch on the form: **Active** sends reminders,\r\n  **Draft** sends nothing.\r\n\r\n- **\"Completed\" is gone, and \"Ended\" is worked out from the dates** — Completed was a third state\r\n  that no code ever set and no administrator remembered to. Whether a review is finished is a\r\n  fact about one person's assessment, not about the cycle. A cycle whose end date has passed now\r\n  reads as **Ended** without anyone marking it, and sends nothing further.\r\n\r\n- **The question-set picker has been removed** — It stored a preference that nothing ever read.\r\n\r\n### Reminders\r\n\r\n- **Reviews are now chased at all** — A cycle creates no forms and assigns no assessors, so\r\n  without a reminder it was a row nobody ever heard about. A daily job now sends them, and it is\r\n  scheduled in both deployment files in the same change — every reminder endpoint in this product\r\n  had previously been written, tested and merged while no scheduler ever invoked it.\r\n\r\n- **Two reminders by default, and as many as you want** — 14 days ahead, when there is still time\r\n  to arrange something, and 3 days ahead, when it has to be done. One reminder is either too\r\n  early to act on or too late to prepare for. Administrators can choose 30 days, a week, a day,\r\n  the day itself, or any other number, up to six per cycle.\r\n\r\n- **Setting a cycle up late still produces one timely reminder** — Configuring a hire-date cycle\r\n  two days before somebody's anniversary means both the 14-day and 3-day marks have already\r\n  passed. Sending nothing would lose the reminder entirely, and sending both would deliver two\r\n  emails at once, one of them claiming the review is a fortnight away. Only the most recent\r\n  milestone that has come due is sent, and it counts the days from the real dates.\r\n\r\n- **Reminders reach the people who have to act** — The employee's department head, plus\r\n  executives and administrators. Where a department has no head, the employee's manager is\r\n  reminded instead, so two people are not each left assuming the other owns it. The employee is\r\n  not reminded about their own review; anyone matching several of these receives one email rather\r\n  than one per role.\r\n\r\n- **1:1 reminders go out a week ahead, the day before, and on the day** — A single reminder the\r\n  evening before is too late to prepare for and too late to move.\r\n\r\n### 1:1 meetings\r\n\r\n- **A 1:1 has a time and a duration** — Previously only a date, which meant nothing could be put\r\n  in a calendar. The time is a wall-clock time in the organization's timezone, so a recurring 1:1\r\n  stays at the same hour across a daylight-saving change. Thirty minutes by default, changeable.\r\n\r\n- **The meeting appears in Google Calendar and Outlook** — One event with both people invited as\r\n  attendees, so it can be accepted or declined like any other invitation, rather than two\r\n  disconnected copies that cannot be declined at all. Cancelling a meeting, or deleting the\r\n  series, removes the invitation from the calendars it reached — the cancellation email already\r\n  said it had.\r\n\r\n- **A 1:1 arranged for somebody pairs the right two people** — The series was always built as\r\n  \"whoever is signed in\" and the person selected. An administrator standing on an employee's\r\n  profile is arranging a 1:1 **for** that employee, not with them, so every 1:1 set up on\r\n  somebody's behalf paired the administrator with the employee and left out the manager who was\r\n  meant to hold it. Left on the default, the other participant is now the employee's department\r\n  head, or their manager if the department has no head.\r\n\r\n- **Everyone with a stake is told** — Both attendees, whoever arranged it, and the employee's\r\n  manager. It previously notified only \"the other participant\", so one attendee received nothing\r\n  and the arranger received nothing either.\r\n\r\n- **A 1:1 can say which review it is preparing for** — Choosing a running cycle marks the\r\n  conversation as preparation for that review, and the list shows which one. A review\r\n  conversation happens once, so choosing a cycle makes the meeting a single occurrence rather\r\n  than a series.\r\n\r\n- **The list says when the next one is** — Rows named a person and a cadence and left the obvious\r\n  question unanswered. They now read as a date and a time, with the end time too, since a\r\n  calendar entry without a finish cannot be checked for clashes.\r\n\r\n- **A 1:1 is visible to the people with a reason to see it** — Its two participants,\r\n  administrators and executives, the employee's manager, and the head of their department.\r\n  Private notes stay visible only to whoever wrote them.\r\n\r\n### Seeing your own schedule\r\n\r\n- **A profile now says when the next review is due** — A review cycle records no assessment until\r\n  one is written, so nothing about it reached the person it covered: an administrator could set up\r\n  a cycle across the whole company and every profile still read \"Not in a review cycle\". The\r\n  schedule existed only in Settings and in the reminder emails leadership received.\r\n\r\n  The Reviews tab now opens with **Coming up** — the cycles covering that person and the date each\r\n  one falls due, worked out from their own start date for a hire-date cycle or from the window for\r\n  a fixed one. Recorded assessments follow underneath.\r\n\r\n  Only running cycles appear, and only where the scope covers the person. A closed window, a\r\n  one-off milestone that has passed, and anyone with no start date on file are left out rather\r\n  than shown as overdue.\r\n\r\n### Recording a review\r\n\r\n- **A review can be marked complete** — The Coming up list said when a review was due and\r\n  offered nothing to do about it. Opening one now records that it happened, who recorded it and\r\n  when. Reopening clears that stamp, so the record never claims a completion that was undone.\r\n\r\n- **Notes, with three levels of visibility** — A note on a review says who may read it, named by\r\n  the roles the product actually has: **Employee and above**, **Department Head and above**, or\r\n  **Administrator and Executive only**. Each level is readable by everyone above it, and the\r\n  author always sees their own. Hovering a level spells the roles out in full.\r\n\r\n  Administrator and Executive only is how something is kept from a department head as well as\r\n  from the employee. A department head writes at the first two levels for their own department,\r\n  and cannot write a note their own leadership could not read.\r\n\r\n  Visibility is stored as a level rather than a list of people, so it stays correct when somebody\r\n  changes department or is promoted — a note written for \"managers\" is readable by whoever heads\r\n  that person's department today.\r\n\r\n- **A Review mode on the upload page** — A third way to send, beside Upload to folder and\r\n  Send for signature. It asks in the order the work happens: the review cycle, the document,\r\n  the people who sign, and then which of them is being reviewed. The document is then openable\r\n  from that person's Performance tab instead of being hunted for in the documents list.\r\n\r\n  The first attempt put a single picker inside the Recipients panel listing every recipient\r\n  crossed with every review they had — \"Aiden Ramirez — FY26 Annual Review — Aug 24, 2026\" and\r\n  five more lines like it. That list grows multiplicatively, it put the review after the people\r\n  it depends on, and the part that identifies the document, the cycle, was the part repeated\r\n  rather than the part chosen. A review is a cycle plus a person, so those are now two separate\r\n  questions and there is no combined list at all.\r\n\r\n  Only cycles that are running are offered, and every review the person is scheduled for counts\r\n  — a cycle's dates are derived, so an active cycle covering somebody is a real review with\r\n  nothing stored against it yet. Offering only already-recorded ones left the list empty for\r\n  almost everybody. The record is created as the document is sent. A cycle that does not cover\r\n  the chosen person says so in words rather than going blank.\r\n\r\n- **The employee owns the review document, whoever signs first** — A review form is routinely\r\n  countersigned by the department head and then the employee. The document used to belong to\r\n  whoever was added as the first recipient, so listing the manager first put the form on the\r\n  manager's profile and then refused the upload outright, because the review belongs to the\r\n  employee. Whose review it is and who signs in what order are now separate questions: the\r\n  employee owns it either way, and the signing order is yours to set as on any other document.\r\n\r\n  With a single recipient there is nothing to decide and the answer fills itself in. Adding a\r\n  second clears it rather than leaving the first person marked — which is precisely how a\r\n  manager would otherwise end up recorded as the subject of their own report's review.\r\n\r\n- **A review exists only once somebody acts on it** — Dates are derived from the cycle, so there\r\n  is nothing to store until a review is completed, noted or has a document attached. Creating\r\n  that record is idempotent on the cycle, the person and the date, so two people acting at once\r\n  get one review rather than two.\r\n\r\n### What an employee can see of their own performance\r\n\r\n- **The Performance tab is on your own profile** — Your goals, the 1:1s you attend and the\r\n  reviews you are the subject of were all gated to administrators, executives and department\r\n  heads, so an employee could not see a goal set for them or when their own review falls due.\r\n  The tab is now on your own profile, read-only: every control that writes stays gated, and\r\n  notes and comments are still filtered to what was shared with you.\r\n\r\n  Nothing was unlocked on the server to do this. Every read already allowed your own record —\r\n  only the tab was in the way.\r\n\r\n- **An unfinished assessment is no longer readable by its subject** — An assessment is created\r\n  before anybody writes in it, and the assessor fills in the rating and comments before\r\n  submitting. The endpoint applied no status filter, so the person being assessed could read a\r\n  half-written candid rating of themselves while its author was still drafting it. Only\r\n  completed assessments are returned to their subject now; the assessor still sees their own\r\n  work in progress.\r\n\r\n- **Peer and upward feedback is no longer attributed to its author** — A PEER or DIRECT_REPORT\r\n  assessment came back to its subject with the assessor's name and id attached, which defeats\r\n  the confidentiality those two kinds of review are collected under. The content is still\r\n  shown; the author is not. A manager assessment keeps its attribution, which is the point of\r\n  one.\r\n\r\n  Both were pre-existing, and both became reachable through ordinary use the moment the\r\n  Performance tab opened to employees — so they are fixed in the same change rather than left\r\n  for the next one to find.\r\n\r\n- **Goal comments carry a visibility level** — The same three levels as review notes, so a\r\n  manager can note something about a goal without it being readable by the person the goal\r\n  belongs to. The control, the wording and the levels are identical to the ones on a review, on\r\n  the principle that a comment about somebody is the same kind of writing wherever it is\r\n  written.\r\n\r\n  The default is **Employee and above**, where a review note defaults to Department Head and\r\n  above. A review note is written about somebody; a goal comment is a conversation with them on\r\n  a goal whose progress they own. Existing comments are all Employee and above, so no thread\r\n  that was readable yesterday stopped being readable.\r\n\r\n- **A department head can read the discussion on their own department's goals** — They could\r\n  already read the goals themselves, but the comments on them were restricted to administrators\r\n  and executives, which is the same inconsistency the write side had.\r\n\r\n### Documents\r\n\r\n- **Word documents and images preview instead of refusing** — Filing accepts PDF, DOC, DOCX,\r\n  PNG, JPG and JPEG, and the preview handled only the first of those. Everything else got \"Only\r\n  PDF documents are supported for preview\", which reads as a fault rather than a limitation,\r\n  above a Try Again button that could never succeed. A `.docx` now renders as pages in the\r\n  browser, and an image renders as an image.\r\n\r\n  The rendering happens in the browser, so the file never goes to a conversion service. The\r\n  older binary `.doc` format has no browser renderer, so it says so by name and offers the\r\n  download, rather than being lumped in with everything else.\r\n\r\n- **The same click behaves the same everywhere** — Opening a document from an employee's folder\r\n  used to fetch the bytes and hand them to the browser, which downloaded a Word file instead of\r\n  showing it, while the same document opened from the documents list previewed. Both now use\r\n  the preview.\r\n\r\n- **A damaged file says so in our own words** — A truncated upload kept its PDF header, so it\r\n  reached the browser's viewer and drew that viewer's black \"Failed to load PDF document\" panel\r\n  inside the preview, with a Reload that could not help. The file is checked for both its header\r\n  and its closing marker first, and a file that fails gets a plain explanation and the download\r\n  button, which is the thing that actually works.\r\n\r\n### Rescheduling a 1:1\r\n\r\n- **The date of the next 1:1 can be changed** — Editing a 1:1 offered the cadence, the time and\r\n  the duration, but no date, so moving one to another day meant deleting it and setting it up\r\n  again — losing the agenda, the notes and the calendar entry with it. Changing the time still\r\n  moves every upcoming meeting that follows the series; changing the date moves only the next\r\n  one.\r\n\r\n### Who sets performance up\r\n\r\n- **Performance is run for people, not by them** — Creating a 1:1 or a goal was allowed for\r\n  \"you, or an administrator\", which put a **New 1:1** and an **Add Goal** button on every profile\r\n  for everyone, including people arranging their own reviews. Now an executive may act for\r\n  anyone including themselves; an administrator for anyone except themselves; a department head\r\n  for their own department, but not for themselves; and nobody else at all.\r\n\r\n- **A department head can finally set one up for their own people** — The previous rule gave them\r\n  no way to, despite being the person who actually holds those conversations.\r\n\r\n- **The same rule now covers goal comments** — Commenting on a goal was gated separately on \"an\r\n  administrator, or your own goal\", which disagreed with that rule in three directions at once:\r\n  an employee could annotate their own goal, an administrator could annotate their own, and a\r\n  department head could create a goal for one of their people and then not comment on it. The\r\n  **Add Comment** button is gated to match, as are the delete controls on 1:1s, reviews and\r\n  goals. Whoever wrote a comment may always remove it.\r\n\r\n- **A link to a person's reviews now opens their reviews** — The Reviews tab is stored\r\n  internally under an older name, so a link ending `?perfTab=reviews` quietly opened the 1:1s tab\r\n  instead. It looked like the reviews having vanished rather than like a mistyped address.\r\n\r\n- **The employee still owns their progress** — They move the percentage and the status on a goal\r\n  set for them. The goal's definition — its category and weight — stays with whoever may set it,\r\n  which now includes the department head.\r\n\r\n- **Removing follows the same rule as creating** — Deleting a goal, or a whole 1:1 series, is done\r\n  by whoever runs the conversation. Both previously allowed the subject: an employee could delete\r\n  a goal their manager had set, or a 1:1 series their department head had arranged, along with\r\n  every agenda item and note on it. The buttons are gone for people who may not use them, and the\r\n  endpoints refuse regardless of the buttons.\r\n\r\n### Dates and timezones\r\n\r\n- **A 1:1 books the day the form showed** — The meeting date is a calendar day, with the time of\r\n  day held separately, and it was being parsed as an instant. Every 1:1 booked from a browser\r\n  west of UTC landed on the day before the one displayed. With no date given, \"a week from today\"\r\n  was also counted on the server's clock rather than the organization's.\r\n\r\n- **Anniversaries are counted in the employee's own timezone** — It is their anniversary, so the\r\n  day is resolved for them rather than for the server or whoever is looking.\r\n\r\n### Everywhere else\r\n\r\n- **Destructive actions ask first** — Deleting a 1:1 series, a goal, a goal comment or an agenda\r\n  item now says what is about to be lost and names it. Several of these were a single unguarded\r\n  click, and the ones that did ask used the browser's own dialog, which cannot describe what is\r\n  being removed and which Chrome suppresses after a few uses.\r\n\r\n- **Lists show what is loading** — Goals, reviews and 1:1s rendered their empty state while the\r\n  request was still in flight, so a profile read as \"this person has no goals\" rather than \"not\r\n  loaded yet\".\r\n\r\n- **The profile page uses the full width** — Matching the people and expenses pages.\r\n\r\n- **Vendor names removed from customer-facing copy** — Guided tour text named the specific AI\r\n  models behind a feature. That is an implementation detail, and it dates.\r\n\r\n### Under the hood\r\n\r\n- Review cycle scope, anniversary dates and \"is this cycle running\" each have one implementation\r\n  shared by the screens and the job that sends reminders, after a second copy of the last one let\r\n  the settings list call a cycle Ended while the 1:1 picker still offered it.\r\n- The reminder job de-duplicates on a stored marker keyed by the cycle, the person, the\r\n  anniversary and the milestone, so a retry, restart or overlapping run sends nothing twice.\r\n- The Google and Outlook adapters had each declared their own copy of the same calendar event\r\n  type, and the build was silently discarding one of them.\r\n- The demo lockdown guard is now documented as needing to be run the way CI runs it — scoped to\r\n  the branch's own changes rather than against the whole API, where new handlers were being lost\r\n  in a pre-existing backlog.",{"tag":11,"name":11},"v1.1.2",{"tag":13,"name":13},"v1.0.21",1,{"data":16,"body":17},{},{"type":18,"children":19},"root",[20,29,50,55,60,65,71,187,193,246,252,332,338,368,374,473,479,553,559,614,620,633,639,731,737,760,766,809,815],{"type":21,"tag":22,"props":23,"children":25},"element","h3",{"id":24},"review-cycles-that-actually-run-11s-with-a-time-and-a-calendar-entry-and-a-clear-answer-to-who-sets-performance-up",[26],{"type":27,"value":28},"text","Review cycles that actually run, 1:1s with a time and a calendar entry, and a clear answer to who sets performance up",{"type":21,"tag":30,"props":31,"children":32},"p",{},[33,35,41,43,48],{"type":27,"value":34},"Performance has been rebuilt around a simple split: a ",{"type":21,"tag":36,"props":37,"children":38},"strong",{},[39],{"type":27,"value":40},"review cycle",{"type":27,"value":42}," says when reviews fall\ndue and who they cover, a ",{"type":21,"tag":36,"props":44,"children":45},{},[46],{"type":27,"value":47},"1:1",{"type":27,"value":49}," is the conversation itself, and the two can be linked so a\nreview is something worked towards rather than an event that arrives.",{"type":21,"tag":30,"props":51,"children":52},{},[53],{"type":27,"value":54},"The largest change is that review cycles now do something. A cycle was a name and a pair of\ndates: the scope section on the form was never saved, so a department-wide cycle came out\ncovering everyone, and every cycle ever created was stuck in Draft because nothing in the\nproduct could open it. Cycles now run on either a shared window or each employee's own hire\nanniversary, cover everyone or one department or a chosen list, and send reminders to the people\nresponsible for holding the review.",{"type":21,"tag":30,"props":56,"children":57},{},[58],{"type":27,"value":59},"1:1s gained a time, a duration and a place in the participants' real calendars, and a 1:1\narranged by an administrator now pairs the right two people — previously it paired the\nadministrator with whoever's profile they were standing on.",{"type":21,"tag":30,"props":61,"children":62},{},[63],{"type":27,"value":64},"Alongside those: performance is now something an organization runs for its people rather than\nsomething people set up for themselves, destructive actions ask before they act, and several\ndates that shifted a day west of UTC have been fixed.",{"type":21,"tag":22,"props":66,"children":68},{"id":67},"review-cycles",[69],{"type":27,"value":70},"Review cycles",{"type":21,"tag":72,"props":73,"children":74},"ul",{},[75,100,116,126,136,160,177],{"type":21,"tag":76,"props":77,"children":78},"li",{},[79,84,86,91,93,98],{"type":21,"tag":36,"props":80,"children":81},{},[82],{"type":27,"value":83},"A cycle can follow each employee's hire date",{"type":27,"value":85}," — Annual meant two different things depending\non who set it up: a company-wide window, or a review on each person's own anniversary. One\npair of date columns could not express the second at all. A cycle now chooses between\n",{"type":21,"tag":36,"props":87,"children":88},{},[89],{"type":27,"value":90},"specific dates",{"type":27,"value":92}," — one window for everyone in scope — and ",{"type":21,"tag":36,"props":94,"children":95},{},[96],{"type":27,"value":97},"employee hire date",{"type":27,"value":99},", measured\nfrom each person's own start date with no shared window.",{"type":21,"tag":76,"props":101,"children":102},{},[103,108,110,114],{"type":21,"tag":36,"props":104,"children":105},{},[106],{"type":27,"value":107},"A hire-date cycle is not only the one-year mark",{"type":27,"value":109}," — It says how far after the start date the\nreview falls and whether it recurs: every year on the anniversary, once N months in, or every\nN months. Without that, a cycle named \"3 Months Probation\" would have reminded on the\nemployee's first anniversary. A 29 February start is reviewed on 28 February in years that\nhave no 29th, and a 31st is held to the last day of a shorter month rather than spilling into\nthe next one.",{"type":21,"tag":111,"props":112,"children":113},"br",{},[],{"type":27,"value":115},"This does not replace the probation review on a profile, which keeps its own period, its\nextension date and its own reminders.",{"type":21,"tag":76,"props":117,"children":118},{},[119,124],{"type":21,"tag":36,"props":120,"children":121},{},[122],{"type":27,"value":123},"The Type field is gone",{"type":27,"value":125}," — Annual, Semi-annual, Quarterly, Probation and Custom were a label\nno code ever read. It implied a schedule it did not set: \"Probation\" connected to none of the\nprobation machinery, and \"Custom\" offered nothing to customise. The schedule now says what the\ncycle is, and the name says what to call it.",{"type":21,"tag":76,"props":127,"children":128},{},[129,134],{"type":21,"tag":36,"props":130,"children":131},{},[132],{"type":27,"value":133},"The scope you choose is the scope that is saved",{"type":27,"value":135}," — The form had department and employee\npickers and the endpoint discarded every one of those fields, so an administrator could\nconfigure a department-wide cycle, watch it save, and get a row covering the whole company.\nThere was no column to record a department in. Scope is now stored, the department is checked\nagainst the caller's own organization, and the list shows how many people each cycle currently\ncovers, so a department that has been emptied does not read the same as one with thirty people\nin it.",{"type":21,"tag":76,"props":137,"children":138},{},[139,144,146,151,153,158],{"type":21,"tag":36,"props":140,"children":141},{},[142],{"type":27,"value":143},"A new cycle is running, not stuck in Draft",{"type":27,"value":145}," — The create endpoint ignored the status\nentirely, so every cycle fell through to Draft, and no control anywhere could move it out. A\ncycle is now created Active, and Status is a switch on the form: ",{"type":21,"tag":36,"props":147,"children":148},{},[149],{"type":27,"value":150},"Active",{"type":27,"value":152}," sends reminders,\n",{"type":21,"tag":36,"props":154,"children":155},{},[156],{"type":27,"value":157},"Draft",{"type":27,"value":159}," sends nothing.",{"type":21,"tag":76,"props":161,"children":162},{},[163,168,170,175],{"type":21,"tag":36,"props":164,"children":165},{},[166],{"type":27,"value":167},"\"Completed\" is gone, and \"Ended\" is worked out from the dates",{"type":27,"value":169}," — Completed was a third state\nthat no code ever set and no administrator remembered to. Whether a review is finished is a\nfact about one person's assessment, not about the cycle. A cycle whose end date has passed now\nreads as ",{"type":21,"tag":36,"props":171,"children":172},{},[173],{"type":27,"value":174},"Ended",{"type":27,"value":176}," without anyone marking it, and sends nothing further.",{"type":21,"tag":76,"props":178,"children":179},{},[180,185],{"type":21,"tag":36,"props":181,"children":182},{},[183],{"type":27,"value":184},"The question-set picker has been removed",{"type":27,"value":186}," — It stored a preference that nothing ever read.",{"type":21,"tag":22,"props":188,"children":190},{"id":189},"reminders",[191],{"type":27,"value":192},"Reminders",{"type":21,"tag":72,"props":194,"children":195},{},[196,206,216,226,236],{"type":21,"tag":76,"props":197,"children":198},{},[199,204],{"type":21,"tag":36,"props":200,"children":201},{},[202],{"type":27,"value":203},"Reviews are now chased at all",{"type":27,"value":205}," — A cycle creates no forms and assigns no assessors, so\nwithout a reminder it was a row nobody ever heard about. A daily job now sends them, and it is\nscheduled in both deployment files in the same change — every reminder endpoint in this product\nhad previously been written, tested and merged while no scheduler ever invoked it.",{"type":21,"tag":76,"props":207,"children":208},{},[209,214],{"type":21,"tag":36,"props":210,"children":211},{},[212],{"type":27,"value":213},"Two reminders by default, and as many as you want",{"type":27,"value":215}," — 14 days ahead, when there is still time\nto arrange something, and 3 days ahead, when it has to be done. One reminder is either too\nearly to act on or too late to prepare for. Administrators can choose 30 days, a week, a day,\nthe day itself, or any other number, up to six per cycle.",{"type":21,"tag":76,"props":217,"children":218},{},[219,224],{"type":21,"tag":36,"props":220,"children":221},{},[222],{"type":27,"value":223},"Setting a cycle up late still produces one timely reminder",{"type":27,"value":225}," — Configuring a hire-date cycle\ntwo days before somebody's anniversary means both the 14-day and 3-day marks have already\npassed. Sending nothing would lose the reminder entirely, and sending both would deliver two\nemails at once, one of them claiming the review is a fortnight away. Only the most recent\nmilestone that has come due is sent, and it counts the days from the real dates.",{"type":21,"tag":76,"props":227,"children":228},{},[229,234],{"type":21,"tag":36,"props":230,"children":231},{},[232],{"type":27,"value":233},"Reminders reach the people who have to act",{"type":27,"value":235}," — The employee's department head, plus\nexecutives and administrators. Where a department has no head, the employee's manager is\nreminded instead, so two people are not each left assuming the other owns it. The employee is\nnot reminded about their own review; anyone matching several of these receives one email rather\nthan one per role.",{"type":21,"tag":76,"props":237,"children":238},{},[239,244],{"type":21,"tag":36,"props":240,"children":241},{},[242],{"type":27,"value":243},"1:1 reminders go out a week ahead, the day before, and on the day",{"type":27,"value":245}," — A single reminder the\nevening before is too late to prepare for and too late to move.",{"type":21,"tag":22,"props":247,"children":249},{"id":248},"_11-meetings",[250],{"type":27,"value":251},"1:1 meetings",{"type":21,"tag":72,"props":253,"children":254},{},[255,265,275,292,302,312,322],{"type":21,"tag":76,"props":256,"children":257},{},[258,263],{"type":21,"tag":36,"props":259,"children":260},{},[261],{"type":27,"value":262},"A 1:1 has a time and a duration",{"type":27,"value":264}," — Previously only a date, which meant nothing could be put\nin a calendar. The time is a wall-clock time in the organization's timezone, so a recurring 1:1\nstays at the same hour across a daylight-saving change. Thirty minutes by default, changeable.",{"type":21,"tag":76,"props":266,"children":267},{},[268,273],{"type":21,"tag":36,"props":269,"children":270},{},[271],{"type":27,"value":272},"The meeting appears in Google Calendar and Outlook",{"type":27,"value":274}," — One event with both people invited as\nattendees, so it can be accepted or declined like any other invitation, rather than two\ndisconnected copies that cannot be declined at all. Cancelling a meeting, or deleting the\nseries, removes the invitation from the calendars it reached — the cancellation email already\nsaid it had.",{"type":21,"tag":76,"props":276,"children":277},{},[278,283,285,290],{"type":21,"tag":36,"props":279,"children":280},{},[281],{"type":27,"value":282},"A 1:1 arranged for somebody pairs the right two people",{"type":27,"value":284}," — The series was always built as\n\"whoever is signed in\" and the person selected. An administrator standing on an employee's\nprofile is arranging a 1:1 ",{"type":21,"tag":36,"props":286,"children":287},{},[288],{"type":27,"value":289},"for",{"type":27,"value":291}," that employee, not with them, so every 1:1 set up on\nsomebody's behalf paired the administrator with the employee and left out the manager who was\nmeant to hold it. Left on the default, the other participant is now the employee's department\nhead, or their manager if the department has no head.",{"type":21,"tag":76,"props":293,"children":294},{},[295,300],{"type":21,"tag":36,"props":296,"children":297},{},[298],{"type":27,"value":299},"Everyone with a stake is told",{"type":27,"value":301}," — Both attendees, whoever arranged it, and the employee's\nmanager. It previously notified only \"the other participant\", so one attendee received nothing\nand the arranger received nothing either.",{"type":21,"tag":76,"props":303,"children":304},{},[305,310],{"type":21,"tag":36,"props":306,"children":307},{},[308],{"type":27,"value":309},"A 1:1 can say which review it is preparing for",{"type":27,"value":311}," — Choosing a running cycle marks the\nconversation as preparation for that review, and the list shows which one. A review\nconversation happens once, so choosing a cycle makes the meeting a single occurrence rather\nthan a series.",{"type":21,"tag":76,"props":313,"children":314},{},[315,320],{"type":21,"tag":36,"props":316,"children":317},{},[318],{"type":27,"value":319},"The list says when the next one is",{"type":27,"value":321}," — Rows named a person and a cadence and left the obvious\nquestion unanswered. They now read as a date and a time, with the end time too, since a\ncalendar entry without a finish cannot be checked for clashes.",{"type":21,"tag":76,"props":323,"children":324},{},[325,330],{"type":21,"tag":36,"props":326,"children":327},{},[328],{"type":27,"value":329},"A 1:1 is visible to the people with a reason to see it",{"type":27,"value":331}," — Its two participants,\nadministrators and executives, the employee's manager, and the head of their department.\nPrivate notes stay visible only to whoever wrote them.",{"type":21,"tag":22,"props":333,"children":335},{"id":334},"seeing-your-own-schedule",[336],{"type":27,"value":337},"Seeing your own schedule",{"type":21,"tag":72,"props":339,"children":340},{},[341],{"type":21,"tag":76,"props":342,"children":343},{},[344,349,351,354,356,361,363,366],{"type":21,"tag":36,"props":345,"children":346},{},[347],{"type":27,"value":348},"A profile now says when the next review is due",{"type":27,"value":350}," — A review cycle records no assessment until\none is written, so nothing about it reached the person it covered: an administrator could set up\na cycle across the whole company and every profile still read \"Not in a review cycle\". The\nschedule existed only in Settings and in the reminder emails leadership received.",{"type":21,"tag":111,"props":352,"children":353},{},[],{"type":27,"value":355},"The Reviews tab now opens with ",{"type":21,"tag":36,"props":357,"children":358},{},[359],{"type":27,"value":360},"Coming up",{"type":27,"value":362}," — the cycles covering that person and the date each\none falls due, worked out from their own start date for a hire-date cycle or from the window for\na fixed one. Recorded assessments follow underneath.",{"type":21,"tag":111,"props":364,"children":365},{},[],{"type":27,"value":367},"Only running cycles appear, and only where the scope covers the person. A closed window, a\none-off milestone that has passed, and anyone with no start date on file are left out rather\nthan shown as overdue.",{"type":21,"tag":22,"props":369,"children":371},{"id":370},"recording-a-review",[372],{"type":27,"value":373},"Recording a review",{"type":21,"tag":72,"props":375,"children":376},{},[377,387,428,448,463],{"type":21,"tag":76,"props":378,"children":379},{},[380,385],{"type":21,"tag":36,"props":381,"children":382},{},[383],{"type":27,"value":384},"A review can be marked complete",{"type":27,"value":386}," — The Coming up list said when a review was due and\noffered nothing to do about it. Opening one now records that it happened, who recorded it and\nwhen. Reopening clears that stamp, so the record never claims a completion that was undone.",{"type":21,"tag":76,"props":388,"children":389},{},[390,395,397,402,404,409,411,416,418,421,423,426],{"type":21,"tag":36,"props":391,"children":392},{},[393],{"type":27,"value":394},"Notes, with three levels of visibility",{"type":27,"value":396}," — A note on a review says who may read it, named by\nthe roles the product actually has: ",{"type":21,"tag":36,"props":398,"children":399},{},[400],{"type":27,"value":401},"Employee and above",{"type":27,"value":403},", ",{"type":21,"tag":36,"props":405,"children":406},{},[407],{"type":27,"value":408},"Department Head and above",{"type":27,"value":410},", or\n",{"type":21,"tag":36,"props":412,"children":413},{},[414],{"type":27,"value":415},"Administrator and Executive only",{"type":27,"value":417},". Each level is readable by everyone above it, and the\nauthor always sees their own. Hovering a level spells the roles out in full.",{"type":21,"tag":111,"props":419,"children":420},{},[],{"type":27,"value":422},"Administrator and Executive only is how something is kept from a department head as well as\nfrom the employee. A department head writes at the first two levels for their own department,\nand cannot write a note their own leadership could not read.",{"type":21,"tag":111,"props":424,"children":425},{},[],{"type":27,"value":427},"Visibility is stored as a level rather than a list of people, so it stays correct when somebody\nchanges department or is promoted — a note written for \"managers\" is readable by whoever heads\nthat person's department today.",{"type":21,"tag":76,"props":429,"children":430},{},[431,436,438,441,443,446],{"type":21,"tag":36,"props":432,"children":433},{},[434],{"type":27,"value":435},"A Review mode on the upload page",{"type":27,"value":437}," — A third way to send, beside Upload to folder and\nSend for signature. It asks in the order the work happens: the review cycle, the document,\nthe people who sign, and then which of them is being reviewed. The document is then openable\nfrom that person's Performance tab instead of being hunted for in the documents list.",{"type":21,"tag":111,"props":439,"children":440},{},[],{"type":27,"value":442},"The first attempt put a single picker inside the Recipients panel listing every recipient\ncrossed with every review they had — \"Aiden Ramirez — FY26 Annual Review — Aug 24, 2026\" and\nfive more lines like it. That list grows multiplicatively, it put the review after the people\nit depends on, and the part that identifies the document, the cycle, was the part repeated\nrather than the part chosen. A review is a cycle plus a person, so those are now two separate\nquestions and there is no combined list at all.",{"type":21,"tag":111,"props":444,"children":445},{},[],{"type":27,"value":447},"Only cycles that are running are offered, and every review the person is scheduled for counts\n— a cycle's dates are derived, so an active cycle covering somebody is a real review with\nnothing stored against it yet. Offering only already-recorded ones left the list empty for\nalmost everybody. The record is created as the document is sent. A cycle that does not cover\nthe chosen person says so in words rather than going blank.",{"type":21,"tag":76,"props":449,"children":450},{},[451,456,458,461],{"type":21,"tag":36,"props":452,"children":453},{},[454],{"type":27,"value":455},"The employee owns the review document, whoever signs first",{"type":27,"value":457}," — A review form is routinely\ncountersigned by the department head and then the employee. The document used to belong to\nwhoever was added as the first recipient, so listing the manager first put the form on the\nmanager's profile and then refused the upload outright, because the review belongs to the\nemployee. Whose review it is and who signs in what order are now separate questions: the\nemployee owns it either way, and the signing order is yours to set as on any other document.",{"type":21,"tag":111,"props":459,"children":460},{},[],{"type":27,"value":462},"With a single recipient there is nothing to decide and the answer fills itself in. Adding a\nsecond clears it rather than leaving the first person marked — which is precisely how a\nmanager would otherwise end up recorded as the subject of their own report's review.",{"type":21,"tag":76,"props":464,"children":465},{},[466,471],{"type":21,"tag":36,"props":467,"children":468},{},[469],{"type":27,"value":470},"A review exists only once somebody acts on it",{"type":27,"value":472}," — Dates are derived from the cycle, so there\nis nothing to store until a review is completed, noted or has a document attached. Creating\nthat record is idempotent on the cycle, the person and the date, so two people acting at once\nget one review rather than two.",{"type":21,"tag":22,"props":474,"children":476},{"id":475},"what-an-employee-can-see-of-their-own-performance",[477],{"type":27,"value":478},"What an employee can see of their own performance",{"type":21,"tag":72,"props":480,"children":481},{},[482,497,507,522,543],{"type":21,"tag":76,"props":483,"children":484},{},[485,490,492,495],{"type":21,"tag":36,"props":486,"children":487},{},[488],{"type":27,"value":489},"The Performance tab is on your own profile",{"type":27,"value":491}," — Your goals, the 1:1s you attend and the\nreviews you are the subject of were all gated to administrators, executives and department\nheads, so an employee could not see a goal set for them or when their own review falls due.\nThe tab is now on your own profile, read-only: every control that writes stays gated, and\nnotes and comments are still filtered to what was shared with you.",{"type":21,"tag":111,"props":493,"children":494},{},[],{"type":27,"value":496},"Nothing was unlocked on the server to do this. Every read already allowed your own record —\nonly the tab was in the way.",{"type":21,"tag":76,"props":498,"children":499},{},[500,505],{"type":21,"tag":36,"props":501,"children":502},{},[503],{"type":27,"value":504},"An unfinished assessment is no longer readable by its subject",{"type":27,"value":506}," — An assessment is created\nbefore anybody writes in it, and the assessor fills in the rating and comments before\nsubmitting. The endpoint applied no status filter, so the person being assessed could read a\nhalf-written candid rating of themselves while its author was still drafting it. Only\ncompleted assessments are returned to their subject now; the assessor still sees their own\nwork in progress.",{"type":21,"tag":76,"props":508,"children":509},{},[510,515,517,520],{"type":21,"tag":36,"props":511,"children":512},{},[513],{"type":27,"value":514},"Peer and upward feedback is no longer attributed to its author",{"type":27,"value":516}," — A PEER or DIRECT_REPORT\nassessment came back to its subject with the assessor's name and id attached, which defeats\nthe confidentiality those two kinds of review are collected under. The content is still\nshown; the author is not. A manager assessment keeps its attribution, which is the point of\none.",{"type":21,"tag":111,"props":518,"children":519},{},[],{"type":27,"value":521},"Both were pre-existing, and both became reachable through ordinary use the moment the\nPerformance tab opened to employees — so they are fixed in the same change rather than left\nfor the next one to find.",{"type":21,"tag":76,"props":523,"children":524},{},[525,530,532,535,537,541],{"type":21,"tag":36,"props":526,"children":527},{},[528],{"type":27,"value":529},"Goal comments carry a visibility level",{"type":27,"value":531}," — The same three levels as review notes, so a\nmanager can note something about a goal without it being readable by the person the goal\nbelongs to. The control, the wording and the levels are identical to the ones on a review, on\nthe principle that a comment about somebody is the same kind of writing wherever it is\nwritten.",{"type":21,"tag":111,"props":533,"children":534},{},[],{"type":27,"value":536},"The default is ",{"type":21,"tag":36,"props":538,"children":539},{},[540],{"type":27,"value":401},{"type":27,"value":542},", where a review note defaults to Department Head and\nabove. A review note is written about somebody; a goal comment is a conversation with them on\na goal whose progress they own. Existing comments are all Employee and above, so no thread\nthat was readable yesterday stopped being readable.",{"type":21,"tag":76,"props":544,"children":545},{},[546,551],{"type":21,"tag":36,"props":547,"children":548},{},[549],{"type":27,"value":550},"A department head can read the discussion on their own department's goals",{"type":27,"value":552}," — They could\nalready read the goals themselves, but the comments on them were restricted to administrators\nand executives, which is the same inconsistency the write side had.",{"type":21,"tag":22,"props":554,"children":556},{"id":555},"documents",[557],{"type":27,"value":558},"Documents",{"type":21,"tag":72,"props":560,"children":561},{},[562,594,604],{"type":21,"tag":76,"props":563,"children":564},{},[565,570,572,579,581,584,586,592],{"type":21,"tag":36,"props":566,"children":567},{},[568],{"type":27,"value":569},"Word documents and images preview instead of refusing",{"type":27,"value":571}," — Filing accepts PDF, DOC, DOCX,\nPNG, JPG and JPEG, and the preview handled only the first of those. Everything else got \"Only\nPDF documents are supported for preview\", which reads as a fault rather than a limitation,\nabove a Try Again button that could never succeed. A ",{"type":21,"tag":573,"props":574,"children":576},"code",{"className":575},[],[577],{"type":27,"value":578},".docx",{"type":27,"value":580}," now renders as pages in the\nbrowser, and an image renders as an image.",{"type":21,"tag":111,"props":582,"children":583},{},[],{"type":27,"value":585},"The rendering happens in the browser, so the file never goes to a conversion service. The\nolder binary ",{"type":21,"tag":573,"props":587,"children":589},{"className":588},[],[590],{"type":27,"value":591},".doc",{"type":27,"value":593}," format has no browser renderer, so it says so by name and offers the\ndownload, rather than being lumped in with everything else.",{"type":21,"tag":76,"props":595,"children":596},{},[597,602],{"type":21,"tag":36,"props":598,"children":599},{},[600],{"type":27,"value":601},"The same click behaves the same everywhere",{"type":27,"value":603}," — Opening a document from an employee's folder\nused to fetch the bytes and hand them to the browser, which downloaded a Word file instead of\nshowing it, while the same document opened from the documents list previewed. Both now use\nthe preview.",{"type":21,"tag":76,"props":605,"children":606},{},[607,612],{"type":21,"tag":36,"props":608,"children":609},{},[610],{"type":27,"value":611},"A damaged file says so in our own words",{"type":27,"value":613}," — A truncated upload kept its PDF header, so it\nreached the browser's viewer and drew that viewer's black \"Failed to load PDF document\" panel\ninside the preview, with a Reload that could not help. The file is checked for both its header\nand its closing marker first, and a file that fails gets a plain explanation and the download\nbutton, which is the thing that actually works.",{"type":21,"tag":22,"props":615,"children":617},{"id":616},"rescheduling-a-11",[618],{"type":27,"value":619},"Rescheduling a 1:1",{"type":21,"tag":72,"props":621,"children":622},{},[623],{"type":21,"tag":76,"props":624,"children":625},{},[626,631],{"type":21,"tag":36,"props":627,"children":628},{},[629],{"type":27,"value":630},"The date of the next 1:1 can be changed",{"type":27,"value":632}," — Editing a 1:1 offered the cadence, the time and\nthe duration, but no date, so moving one to another day meant deleting it and setting it up\nagain — losing the agenda, the notes and the calendar entry with it. Changing the time still\nmoves every upcoming meeting that follows the series; changing the date moves only the next\none.",{"type":21,"tag":22,"props":634,"children":636},{"id":635},"who-sets-performance-up",[637],{"type":27,"value":638},"Who sets performance up",{"type":21,"tag":72,"props":640,"children":641},{},[642,666,676,693,711,721],{"type":21,"tag":76,"props":643,"children":644},{},[645,650,652,657,659,664],{"type":21,"tag":36,"props":646,"children":647},{},[648],{"type":27,"value":649},"Performance is run for people, not by them",{"type":27,"value":651}," — Creating a 1:1 or a goal was allowed for\n\"you, or an administrator\", which put a ",{"type":21,"tag":36,"props":653,"children":654},{},[655],{"type":27,"value":656},"New 1:1",{"type":27,"value":658}," and an ",{"type":21,"tag":36,"props":660,"children":661},{},[662],{"type":27,"value":663},"Add Goal",{"type":27,"value":665}," button on every profile\nfor everyone, including people arranging their own reviews. Now an executive may act for\nanyone including themselves; an administrator for anyone except themselves; a department head\nfor their own department, but not for themselves; and nobody else at all.",{"type":21,"tag":76,"props":667,"children":668},{},[669,674],{"type":21,"tag":36,"props":670,"children":671},{},[672],{"type":27,"value":673},"A department head can finally set one up for their own people",{"type":27,"value":675}," — The previous rule gave them\nno way to, despite being the person who actually holds those conversations.",{"type":21,"tag":76,"props":677,"children":678},{},[679,684,686,691],{"type":21,"tag":36,"props":680,"children":681},{},[682],{"type":27,"value":683},"The same rule now covers goal comments",{"type":27,"value":685}," — Commenting on a goal was gated separately on \"an\nadministrator, or your own goal\", which disagreed with that rule in three directions at once:\nan employee could annotate their own goal, an administrator could annotate their own, and a\ndepartment head could create a goal for one of their people and then not comment on it. The\n",{"type":21,"tag":36,"props":687,"children":688},{},[689],{"type":27,"value":690},"Add Comment",{"type":27,"value":692}," button is gated to match, as are the delete controls on 1:1s, reviews and\ngoals. Whoever wrote a comment may always remove it.",{"type":21,"tag":76,"props":694,"children":695},{},[696,701,703,709],{"type":21,"tag":36,"props":697,"children":698},{},[699],{"type":27,"value":700},"A link to a person's reviews now opens their reviews",{"type":27,"value":702}," — The Reviews tab is stored\ninternally under an older name, so a link ending ",{"type":21,"tag":573,"props":704,"children":706},{"className":705},[],[707],{"type":27,"value":708},"?perfTab=reviews",{"type":27,"value":710}," quietly opened the 1:1s tab\ninstead. It looked like the reviews having vanished rather than like a mistyped address.",{"type":21,"tag":76,"props":712,"children":713},{},[714,719],{"type":21,"tag":36,"props":715,"children":716},{},[717],{"type":27,"value":718},"The employee still owns their progress",{"type":27,"value":720}," — They move the percentage and the status on a goal\nset for them. The goal's definition — its category and weight — stays with whoever may set it,\nwhich now includes the department head.",{"type":21,"tag":76,"props":722,"children":723},{},[724,729],{"type":21,"tag":36,"props":725,"children":726},{},[727],{"type":27,"value":728},"Removing follows the same rule as creating",{"type":27,"value":730}," — Deleting a goal, or a whole 1:1 series, is done\nby whoever runs the conversation. Both previously allowed the subject: an employee could delete\na goal their manager had set, or a 1:1 series their department head had arranged, along with\nevery agenda item and note on it. The buttons are gone for people who may not use them, and the\nendpoints refuse regardless of the buttons.",{"type":21,"tag":22,"props":732,"children":734},{"id":733},"dates-and-timezones",[735],{"type":27,"value":736},"Dates and timezones",{"type":21,"tag":72,"props":738,"children":739},{},[740,750],{"type":21,"tag":76,"props":741,"children":742},{},[743,748],{"type":21,"tag":36,"props":744,"children":745},{},[746],{"type":27,"value":747},"A 1:1 books the day the form showed",{"type":27,"value":749}," — The meeting date is a calendar day, with the time of\nday held separately, and it was being parsed as an instant. Every 1:1 booked from a browser\nwest of UTC landed on the day before the one displayed. With no date given, \"a week from today\"\nwas also counted on the server's clock rather than the organization's.",{"type":21,"tag":76,"props":751,"children":752},{},[753,758],{"type":21,"tag":36,"props":754,"children":755},{},[756],{"type":27,"value":757},"Anniversaries are counted in the employee's own timezone",{"type":27,"value":759}," — It is their anniversary, so the\nday is resolved for them rather than for the server or whoever is looking.",{"type":21,"tag":22,"props":761,"children":763},{"id":762},"everywhere-else",[764],{"type":27,"value":765},"Everywhere else",{"type":21,"tag":72,"props":767,"children":768},{},[769,779,789,799],{"type":21,"tag":76,"props":770,"children":771},{},[772,777],{"type":21,"tag":36,"props":773,"children":774},{},[775],{"type":27,"value":776},"Destructive actions ask first",{"type":27,"value":778}," — Deleting a 1:1 series, a goal, a goal comment or an agenda\nitem now says what is about to be lost and names it. Several of these were a single unguarded\nclick, and the ones that did ask used the browser's own dialog, which cannot describe what is\nbeing removed and which Chrome suppresses after a few uses.",{"type":21,"tag":76,"props":780,"children":781},{},[782,787],{"type":21,"tag":36,"props":783,"children":784},{},[785],{"type":27,"value":786},"Lists show what is loading",{"type":27,"value":788}," — Goals, reviews and 1:1s rendered their empty state while the\nrequest was still in flight, so a profile read as \"this person has no goals\" rather than \"not\nloaded yet\".",{"type":21,"tag":76,"props":790,"children":791},{},[792,797],{"type":21,"tag":36,"props":793,"children":794},{},[795],{"type":27,"value":796},"The profile page uses the full width",{"type":27,"value":798}," — Matching the people and expenses pages.",{"type":21,"tag":76,"props":800,"children":801},{},[802,807],{"type":21,"tag":36,"props":803,"children":804},{},[805],{"type":27,"value":806},"Vendor names removed from customer-facing copy",{"type":27,"value":808}," — Guided tour text named the specific AI\nmodels behind a feature. That is an implementation detail, and it dates.",{"type":21,"tag":22,"props":810,"children":812},{"id":811},"under-the-hood",[813],{"type":27,"value":814},"Under the hood",{"type":21,"tag":72,"props":816,"children":817},{},[818,823,828,833],{"type":21,"tag":76,"props":819,"children":820},{},[821],{"type":27,"value":822},"Review cycle scope, anniversary dates and \"is this cycle running\" each have one implementation\nshared by the screens and the job that sends reminders, after a second copy of the last one let\nthe settings list call a cycle Ended while the 1:1 picker still offered it.",{"type":21,"tag":76,"props":824,"children":825},{},[826],{"type":27,"value":827},"The reminder job de-duplicates on a stored marker keyed by the cycle, the person, the\nanniversary and the milestone, so a retry, restart or overlapping run sends nothing twice.",{"type":21,"tag":76,"props":829,"children":830},{},[831],{"type":27,"value":832},"The Google and Outlook adapters had each declared their own copy of the same calendar event\ntype, and the build was silently discarding one of them.",{"type":21,"tag":76,"props":834,"children":835},{},[836],{"type":27,"value":837},"The demo lockdown guard is now documented as needing to be run the way CI runs it — scoped to\nthe branch's own changes rather than against the whole API, where new handlers were being lost\nin a pre-existing backlog.",1790889963334]