{"v":[{"id":1484,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/166#issuecomment-1484","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/166","user":{"id":1,"login":"charles","login_name":"","source_id":0,"full_name":"Charles Willgren","email":"charles@noreply.www-s01.apinet.com","avatar_url":"https:\/\/www-s01.apinet.com\/codeforge\/avatars\/d3c894f7297c5a18eb3f6ac837c335b11a00aa9cc0961323771632b1e2d61bb2","html_url":"https:\/\/www-s01.apinet.com\/codeforge\/charles","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2025-12-08T10:03:41-06:00","restricted":false,"active":false,"prohibit_login":false,"location":"","pronouns":"","website":"","description":"","visibility":"public","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"charles"},"original_author":"","original_author_id":0,"body":"## Where this stands today\n\nThe visit sidebar (`renderSteps()` in `pages\/visit-v2.php`) shows each section with an **answered \/ shown** count. Nothing records which sections the filler has actually opened. The visit stores only `current_step`. So when an answer reveals new questions in a later section, the only sign is a count changing from 4\/4 to 4\/6, which is easy to miss. The Check step lists missing *required* answers, but an optional question that newly appears is never pointed out at all.\n\n## Proposed plan\n\n**Track what has been shown, per question, on the server.** Do not track it per section, and do not track it in the browser.\n* Record a question as **seen** when its section is open and the question is visible at that moment. The page already saves on every step change (`pendingStep`), so the save carries the visible question keys of the section being left and the server records them. Question keys are not PHI. I'd use a small table, `form_v2_visit_seen (fk_form_v2_visit, question_key, first_seen_at, seen_by)`, through a migration. It lives on the server so a visit resumed on another iPad, or after a reload, keeps it.\n* **Waiting** = visible now, not yet seen, and not answered. The server computes it beside `form_v2_visit_progress()` (pure, in `form_v2_visit_rules.inc.php`) and returns it per section with the progress.\n* **The re-flag from the description comes for free.** A question revealed by a later answer was never seen, so its section lights up. If the answer is changed back and the question hides again, the flag goes away. If it was seen once, hidden, then shown again, it stays seen. See question 2.\n\n**On screen:**\n* The sidebar shows a dot and \"*N new*\" on a section with waiting questions, beside the existing count. Inside the section, the waiting questions carry a small **New** label until the section is left.\n* After a save that reveals questions in *another* section, show a short notice: \"This answer added questions in *Emergencies*\", with a link.\n* The Check step lists \"Sections with questions you haven't seen\" above the issues, each with a link.\n\n**Tests:** pure rule cases (seen\/visible\/answered combinations; hidden then revealed), plus a state test showing the seen set survives a reload and that a step change records only that section's visible questions.\n\n## Questions\n\n1. **Should a question that is already filled in from VESTA count as waiting if nobody has opened its section?** Its value came from the record, not from the client. My recommendation: **yes**. \"Seen\" means the filler looked at it, and a prefilled authorization answer is exactly the kind that may be out of date. The flag would then mean \"not looked at\", not \"not answered\". The catch: on a fresh visit every section starts flagged, which is arguably right.\n2. **Seen once, hidden, then revealed again with its old answer:** flag it again? The plan (\u00a76) says a reactivated branch \"requires review before those saved answers become current again\". That suggests **yes**, so I'd clear \"seen\" when a question hides. Please confirm.\n3. **Does a waiting question block Generate forms?** I'd **block**, with the list of sections as the reason. Otherwise forms can be printed with a question nobody asked. The alternative is a warning the filler can override. This is the same decision as question 3 on #165.\n\n#165 depends on this for its \"revisit these sections\" half, so I'd build this one first.\n\n","assets":[],"created_at":"2026-10-07T23:17:03-05:00","updated_at":"2026-10-07T23:17:03-05:00"},{"id":1519,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/166#issuecomment-1519","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/166","user":{"id":1,"login":"charles","login_name":"","source_id":0,"full_name":"Charles Willgren","email":"charles@noreply.www-s01.apinet.com","avatar_url":"https:\/\/www-s01.apinet.com\/codeforge\/avatars\/d3c894f7297c5a18eb3f6ac837c335b11a00aa9cc0961323771632b1e2d61bb2","html_url":"https:\/\/www-s01.apinet.com\/codeforge\/charles","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2025-12-08T10:03:41-06:00","restricted":false,"active":false,"prohibit_login":false,"location":"","pronouns":"","website":"","description":"","visibility":"public","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"charles"},"original_author":"","original_author_id":0,"body":"## Built (fcc5d40)\n\n**Decisions on the three questions**\n1. **A question filled in from VESTA does not count as waiting** unless it was seen and later hidden. Waiting = shown, never seen, and unanswered.\n2. **Seen, hidden, then shown again: yes, it waits again**, even with its old answer still in it (FormsV2Plan \u00a76 reactivation review).\n3. **Waiting questions block Generate forms.** The refusal names the sections. A Superuser's \"skip the check\" also skips this. This also answers #165 question 3.\n\n**How it works**\n* New table `form_v2_visit_seen` (`migrations\/20261008_visit-seen-questions.sql`). It holds question keys and dates only, no PHI. A question is **seen** once it was on screen in a section the filler then left. The page sends `left` (the sections it left) with its save, and that includes going to Check. The server marks what those sections showed *before* the save's own changes. So a question the save reveals in the section being left is still flagged. A seen question that a change hides is cleared, in the same transaction.\n* The rules are pure functions in `form_v2_visit_rules.inc.php`: `form_v2_visit_is_waiting()`, `form_v2_visit_waiting()`, `form_v2_visit_seen_changes()` and `form_v2_visit_unseen_steps()`. `form_v2_visit_progress()` now returns `waiting` per section and overall.\n* The check returns `unseen`. `form_v2_candidate_prepare()` refuses with the new code `unseen`, after `issues`.\n\n**On screen (`\/visit-v2`)**\n* The sidebar shows a dot and \"N new\" under the section count.\n* Waiting questions carry a **New** label until the section is left.\n* When an answer brings up questions in another section, a notice says \"This answer added questions in *Transfer and choice*\", with a link.\n* The Check step lists \"Sections with questions you haven't seen\" above the issues, each with a link.\n\n**Tests:** new cases in `test-form-v2-visit-rules` (233 pass), `test-form-v2-visit-state` (146 pass) and `test-form-v2-candidate-state` (64 pass). One existing case in the candidate test was adjusted: its visit had an optional question nobody had opened, so it now hit the new refusal before the \"no blank form\" one it was testing. Also checked in the browser on dev visit 75.\n\n**To deploy:** `php scripts\/migrate.php --apply`.","assets":[],"created_at":"2026-10-08T10:13:36-05:00","updated_at":"2026-10-08T10:13:36-05:00"}]}