{"v":[{"id":955,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/80#issuecomment-955","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/80","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":"Done as part of #77\/#78 (5 Oct 2026).\n\n- **FormsV2Plan:** new \u00a74.1.3 \"The form's wording and numbers are the question's\" explicitly reverses the spoken-label design. A question's label is the paper's wording; our wording moved to `say` (\"Ask: \u2026\"). The \u00a74.1.2 rule that the form's explanatory text must be on screen still stands. \u00a74.1.2 was left as history rather than rewritten, because \u00a74.1.3 overrides it by name.\n- **`docs\/form-v2-interviews\/README.md`:** says the label is the form's own wording (leave `label` out to get it) and `say` is how to ask it aloud.\n- **Project memory** (`feedback_v2_placement_by_claude`): marked superseded 2026-10-05 with the new rule.\n\n**Still open, tracked on #77:** the customer's choice of wording for the 40 questions where the forms disagree, and the three choice lists (emergency class, sex, service tasks). Until then those keep our wording, and the \"which forms\" panel shows each form's own.","assets":[],"created_at":"2026-10-05T11:21:05-05:00","updated_at":"2026-10-05T11:21:05-05:00"},{"id":958,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/79#issuecomment-958","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/79","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":"Status, 5 Oct 2026.\n\n**On each question: done** (shipped with #77\/#78). The \u24d8 \"Which forms this goes on\" panel lists every form the answer prints on, that form's own wording, and a link to the blank. The label shows \"Form 3040, item 8\" where the form prints item numbers.\n\n**Visit's list of documents: done in the repo, not yet published.** Rule: a form's number is used only when the filename or the paper itself shows it, in the format **\"Form N \u2013 Name\"**:\n- Form 3040 \u2013 Attendant Orientation \/ Supervisory Visit (filename)\n- Form H2076 \u2013 Authorization to Release Medical Information (printed)\n- Form 2101 \u2013 Authorization for Community Care Services (printed on the faxed copy)\n- Form 3052 \u2013 MD Order (reformatted)\n- Form TDEM 21 \u2013 STEAR, State of Texas Emergency Assistance Registry (blank catalogue only)\n\nThe other SOC forms (consents, Client Information Sheet, Coordination of Care, ISP, etc.) print no number and keep their names. Changed in `docs\/form-packets\/*.json` (the document list), the two definitions, and `code\/form_blanks.inc.php`. `scripts\/test-form-blanks.php` now fails on a numbered title in any other format.\n\n**To apply:** `import-form-packets.php --publish --as=\u2026`, then `form-v2-pipeline.php --packet=SOC_AO --apply --as=\u2026` for the two definition titles. Close once it is visible on a visit.","assets":[],"created_at":"2026-10-05T11:21:06-05:00","updated_at":"2026-10-05T11:21:06-05:00"},{"id":960,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/79#issuecomment-960","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/79","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":"Published on dev and confirmed: the form numbers show in the visit's list of documents. Closing.","assets":[],"created_at":"2026-10-05T11:28:03-05:00","updated_at":"2026-10-05T11:28:03-05:00"},{"id":963,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/92#issuecomment-963","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/92","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, not yet published (5 Oct 2026).**\n\n- Authorized weekly hours are no longer a question. `auth.weekly_hours` is in `FORM_V2_FROZEN_KEYS`, so it prints straight from the visit's copy of the VESTA authorization and no answer can change it. The data dictionary went to version 3, so every interview and release has to be republished.\n- The visit's schedule step shows **\"Authorized: 20.00 hours a week\"**, read-only, under the totals, and says *\"The schedule is X hours over\"* when the schedule adds up to more. This is a notice only. Enforcing the limit is H3.\n- The question is gone from `docs\/form-v2-interviews\/SOC_AO.json`, and the service plan step's intro says where the hours are shown now.\n- **`auth.days_per_week` stays asked.** The customer said the time frame may change, and days per week is the time frame.\n- The Form Explorer shows it as *\"Shown from the authorization, cannot be changed at the visit\"*.\n\n**To finish:** the drafts are imported on dev (`form-v2-pipeline.php --packet=SOC_AO --import --replace`) and the rehearsal passes all nine checks. Next: review and publish on `\/admin\/form-v2-publish`, then choose the release on `\/admin\/form-v2-releases`.","assets":[],"created_at":"2026-10-05T11:39:41-05:00","updated_at":"2026-10-05T11:39:41-05:00"},{"id":964,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/91#issuecomment-964","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/91","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, not yet published (5 Oct 2026).**\n\n- Times are still entered as start and end. **Each attendant's day has to come out in quarter hours.** The server refuses a `schedule.attendant_N_{day}` cell whose total isn't a multiple of 15 minutes (`FORM_V2_SCHEDULE_STEP_MINUTES`). The refusal says what the times come to: *\"These times come to 1 hour 10 minutes. Each day's hours must come out in quarter hours (1.00, 1.25, 1.50, 1.75), so move a start or end time.\"* Odd minutes that add up are fine (8:10\u20139:25 = 1.25), and a split day is judged on its total.\n- The visit page marks an off-step day in red as it is typed, and shows every hours figure to two decimals (cells, per-attendant week, all-attendant totals).\n- A VESTA schedule day that is off the step isn't carried into the visit. The supervisor sees \"VESTA has \u2026, which could not be used\" and enters it properly.\n- **The printed forms show two decimals.** There's a new `decimals` key on `number` fields, set to 2 on all 30 hours boxes: the 3040 (schedule totals, hours per attendant, authorized hours), the service plan (schedule totals, Total Hours) and both consents (hours per week).\n\n**To finish:** same publish as #92. It needs new versions of the 3040, the service plan and both consent forms, which the pipeline rehearsal already covers.","assets":[],"created_at":"2026-10-05T11:39:42-05:00","updated_at":"2026-10-05T11:39:42-05:00"},{"id":966,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/86#issuecomment-966","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/86","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, not yet published (5 Oct 2026).**\n\n- The service end date question is removed from `docs\/form-v2-interviews\/SOC_AO.json` and recorded in its `not_asked`, with the customer's reason.\n- Only one form prints it: the service plan's \"End Date (if applicable)\". No form requires it, so the publish check accepts it. It now prints blank, because a value that isn't asked is never projected, even though VESTA has one.\n- The Form Explorer shows it as *\"Not asked: prints blank\"*, with the reason.\n\n**To finish:** same publish as #92 \/ #91.","assets":[],"created_at":"2026-10-05T11:39:42-05:00","updated_at":"2026-10-05T11:39:42-05:00"},{"id":969,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/91#issuecomment-969","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/91","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":"**Changed:** a VESTA schedule day that doesn't come out in quarter hours is now **still filled in**. It carries the same message a typed one gets (\"These times come to 1 hour 10 minutes. Each day's hours must come out in quarter hours\u2026\"), shown under the cell and listed on the visit's check. The forms can't be printed for signing until it is fixed. A day the supervisor types off the quarter hour is still refused when saved. The rule lives in one place (`form_v2_visit_value_problem()`), and the save, the check and the page all read it.","assets":[],"created_at":"2026-10-05T11:43:02-05:00","updated_at":"2026-10-05T11:43:02-05:00"},{"id":970,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/92#issuecomment-970","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/92","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":"Committed in efc8b74. Closing. To reach the customer, the SOC_AO release still has to be published (`\/admin\/form-v2-publish`) and chosen for each agency (`\/admin\/form-v2-releases`).","assets":[],"created_at":"2026-10-05T11:54:03-05:00","updated_at":"2026-10-05T11:54:03-05:00"},{"id":971,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/91#issuecomment-971","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/91","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":"Committed in efc8b74. Closing. To reach the customer, the SOC_AO release still has to be published (`\/admin\/form-v2-publish`, which includes new versions of the 3040, the service plan and both consent forms) and chosen for each agency (`\/admin\/form-v2-releases`).","assets":[],"created_at":"2026-10-05T11:54:03-05:00","updated_at":"2026-10-05T11:54:03-05:00"},{"id":972,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/86#issuecomment-972","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/86","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":"Committed in efc8b74. Closing. To reach the customer, the SOC_AO release still has to be published (`\/admin\/form-v2-publish`) and chosen for each agency (`\/admin\/form-v2-releases`).","assets":[],"created_at":"2026-10-05T11:54:03-05:00","updated_at":"2026-10-05T11:54:03-05:00"},{"id":977,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/138#issuecomment-977","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/138","user":{"id":3,"login":"connect-bot","login_name":"","source_id":0,"full_name":"","email":"connect-bot@noreply.www-s01.apinet.com","avatar_url":"https:\/\/www-s01.apinet.com\/codeforge\/avatars\/68a2723f7ad70dee2e1415be7488d84b","html_url":"https:\/\/www-s01.apinet.com\/codeforge\/connect-bot","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2026-10-01T08:49:35-05: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":"connect-bot"},"original_author":"","original_author_id":0,"body":"**Charles W.** _(via Connect)_\n<!-- connect:user=1 -->\n\nThe form blank includes pre-filled \"Fall or Injury\" and \"Rash or Skin Breakdown\" as those are the health problems the attendant must report. We don't change the wording on the interview but we include those two items. The form is answered yes\/no as an acknowledgement. When generating, put checks on the items on the form if they answer Yes.","assets":[],"created_at":"2026-10-05T11:58:56-05:00","updated_at":"2026-10-05T11:58:56-05:00"},{"id":978,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/138#issuecomment-978","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/138","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":"Done in the files (not yet committed or published):\n\n- **Definition** (`docs\/forms\/forms-3040.json`): `ori_report_health_problems` is now a Yes\/No (`checkbox`) instead of free text. Its help text lists the two problems as the paper prints them (Fall or Injury, Rash or Skin Breakdown), so they show with the question.\n- **Interview** (`SOC_AO.json`): the wording is unchanged (\"Which health problems must the attendant report?\"). The help now says to answer Yes once the attendant has been told.\n- **Printing** (`docs\/form-placements\/forms-3040.json`): a Yes puts an X in item 10-4's box (it was not placed before) and a \u2713 beside each of the two printed problems. A No prints nothing. Checked on a proof.\n- **Pipeline fix** found along the way: the interview import was seeded from the *published* definitions but checked against the new ones, so a field whose type changed was refused on every run. The import now reads the definitions about to be published. Pinned in `test-form-v2-pipeline-state`.\n\nDefaulting it to Yes is left to #101, which is still open.\n\nTo ship: `form-v2-pipeline.php --packet=SOC_AO --import` (already rehearsed clean on dev), then review and publish on `\/admin\/form-v2-publish`.","assets":[],"created_at":"2026-10-05T12:06:29-05:00","updated_at":"2026-10-05T12:06:29-05:00"},{"id":984,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/146#issuecomment-984","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/146","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":"Fixed in `pages\/admin\/systems-edit.php` (not yet committed).\n\n**What was wrong:** the single \"Vesta Agency ID\" box saved a `vesta_agency_id` system setting that **nothing reads**. The pipeline maps VESTA agency \u2192 system with the constant `HH_AGENCY_SYSTEM` in `code\/functions_hhm.inc.php` (347 + 353 \u2192 11, 524 \u2192 10, 354 \u2192 9). Typing a second ID into the box would have changed nothing.\n\n**What changed:** the box is replaced by a read-only list of every VESTA agency ID that feeds the system, taken from `HH_AGENCY_SYSTEM` and named from `$SITE['agencies']`. For example, system 11 shows `347 LHHA CBR` and `353 LHHA RGV`, with the note \"Set in the data pipeline, not here.\" The save no longer writes the setting. Any old rows are left in place, unread. I checked that system 11 renders correctly on dev.\n\n**Not done:** making the mapping editable on screen. That would mean moving `HH_AGENCY_SYSTEM`, the CLI loaders' local `AGENCY_SYSTEM` copies and `get-reports.js`'s list into the database. If that's wanted, it should be its own issue.\n\nChangelog and UserChangelog updated.","assets":[],"created_at":"2026-10-05T13:27:36-05:00","updated_at":"2026-10-05T13:27:36-05:00"},{"id":985,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/146#issuecomment-985","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/146","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":"Closing. The systems editor now lists every VESTA agency ID that feeds a system, read-only, from `HH_AGENCY_SYSTEM`. Making the mapping editable on screen would be a separate issue, if it's wanted.","assets":[],"created_at":"2026-10-05T13:29:54-05:00","updated_at":"2026-10-05T13:29:54-05:00"},{"id":987,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/144#issuecomment-987","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/144","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":"Done in ac295e1 (`pages\/admin\/systems-edit.php`):\n\n* **Logo** moved into the right-hand column with the color settings.\n* **Unexplained blank fields** removed. These were eight `office_*` \/ `mailing_*` address settings with no label. The save ignored them and nothing read them; the agency's address is the Address field in the Agency section.\n* **Agency section** is now a compact two-column grid with one shared help line. System Name, Short Name and the VESTA agency IDs share a row, and each color is paired with a small preview swatch.\n* **Help text** no longer mentions form prefill.\n\nThe VESTA agency ID box was then changed to a read-only list in #146.","assets":[],"created_at":"2026-10-05T13:30:31-05:00","updated_at":"2026-10-05T13:30:31-05:00"},{"id":990,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/138#issuecomment-990","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/138","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":"Closing: 10-4 is now a Yes\/No reminder, and a Yes ticks the box and checks both printed problems (details above). It reaches visits with the next SOC\/AO publish on `\/admin\/form-v2-publish`. Defaulting it to Yes is tracked in #101.","assets":[],"created_at":"2026-10-05T13:31:49-05:00","updated_at":"2026-10-05T13:31:49-05:00"},{"id":993,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/142#issuecomment-993","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/142","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":"Confirmed on production: the agency administrator is set to \"Ambrose Hernandez\". All good \u2014 closing.","assets":[],"created_at":"2026-10-05T14:08:29-05:00","updated_at":"2026-10-05T14:08:29-05:00"},{"id":995,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/87#issuecomment-995","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/87","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":"Done in the working tree (not yet committed or published). `shared.supervision_level` is now a fixed value (new derive op `fixed` in `code\/form_v2_shared.inc.php`): it's never asked and always prints **Non-RN**, which is how both the service plan's \"Plan of Supervision\" and the 3040's \"Level of Supervision\" say Supervisor. The question is gone from `docs\/form-v2-interviews\/SOC_AO.json`. Takes effect after `form-v2-pipeline.php --packet=SOC_AO --import --replace` and a publish.","assets":[],"created_at":"2026-10-05T14:17:29-05:00","updated_at":"2026-10-05T14:17:29-05:00"},{"id":996,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/96#issuecomment-996","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/96","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":"**Decision (owner, 5 Oct 2026):** remove the question and always print Yes.\n\nDone in the working tree (not yet committed or published). New fixed value `shared.continues_to_need_services` (claims `forms-3040.continues_to_need_services`), which always prints **Yes** on 3A. The question is gone from `SOC_AO.json`. Takes effect after the SOC_AO import and publish.","assets":[],"created_at":"2026-10-05T14:17:29-05:00","updated_at":"2026-10-05T14:17:29-05:00"},{"id":997,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/97#issuecomment-997","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/97","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":"Done in the working tree (not yet committed or published). New fixed value `shared.schedule_variable` (claims `forms-3040.schedule_variable`), which always marks **\"Is not variable\"**. No follow-up questions depended on it. The question is gone from `SOC_AO.json`. Takes effect after the SOC_AO import and publish.","assets":[],"created_at":"2026-10-05T14:17:29-05:00","updated_at":"2026-10-05T14:17:29-05:00"},{"id":998,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/139#issuecomment-998","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/139","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":"Done in the working tree (not yet committed or published).\n\n1. The paper reads \"ATTENDANT SCHEDULE (for use by provider agency) FWD: ____  Schedule \u2610 Is \u2610 Is not variable\". The blank is a date, which fits \"pulls from Service Plan Start Date\". The paper doesn't spell out \"FWD\".\n2. `forms-3040.schedule_fwd` is now a `date` field prefilled from `auth.service_start_date`, the same value the service plan prints as its Start Date. So it's one question, asked on the service plan step and confirmed against VESTA, and the 3040 prints it as a date (placement `format: date`). The Explorer shows its source as that question. The free-text \"Schedule note (FWD)\" question is removed from `SOC_AO.json`.\n\nTakes effect after the SOC_AO import and publish.","assets":[],"created_at":"2026-10-05T14:17:29-05:00","updated_at":"2026-10-05T14:17:29-05:00"},{"id":999,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/87#issuecomment-999","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/87","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":"Deployed to production 5 Oct 2026. Closing.","assets":[],"created_at":"2026-10-05T14:21:35-05:00","updated_at":"2026-10-05T14:21:35-05:00"},{"id":1000,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/96#issuecomment-1000","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/96","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":"Deployed to production 5 Oct 2026. Closing.","assets":[],"created_at":"2026-10-05T14:21:35-05:00","updated_at":"2026-10-05T14:21:35-05:00"},{"id":1001,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/97#issuecomment-1001","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/97","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":"Deployed to production 5 Oct 2026. Closing.","assets":[],"created_at":"2026-10-05T14:21:35-05:00","updated_at":"2026-10-05T14:21:35-05:00"},{"id":1002,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/139#issuecomment-1002","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/139","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":"Deployed to production 5 Oct 2026. Closing.","assets":[],"created_at":"2026-10-05T14:21:35-05:00","updated_at":"2026-10-05T14:21:35-05:00"},{"id":1008,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/78#issuecomment-1008","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/78","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":"Deployed to production 5 Oct 2026. The visit screen shows \"Form 3040, item N\" beside each question the 3040 numbers, and the Form Explorer shows the number on each box row. The 3040 is the only Start of Care form that prints question numbers.\n\nThe leftover \"add the numbers to the data-element list (R1)\" isn't needed. That list was a one-off snapshot from 29 Sep, and the Form Explorer replaced it; the Explorer already shows the numbers. Closing.","assets":[],"created_at":"2026-10-05T14:24:13-05:00","updated_at":"2026-10-05T14:24:13-05:00"},{"id":1012,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/89#issuecomment-1012","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/89","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":"**Done (5 Oct 2026).** The service plan's tasks are now the tasks authorized in VESTA, and they can't be changed at the visit.\n\n**What the supervisor sees**\n- The service plan step shows \"The tasks the client is authorized for\", read-only, in place of the tick list. It says that a wrong task is fixed by asking the office to correct the authorization in VESTA, the same route as the hours (#92).\n- If VESTA lists no tasks for the client, the step says so instead of showing an empty list.\n\n**What prints**\n- The service plan, the coordination of care form and the task guide (#102) all print from that one list.\n- **\"Other tasks\"** is no longer asked. A task VESTA doesn't list isn't authorized, so the \"Other\" task lines on the service plan and the coordination of care form print blank.\n\n**Checked on dev** (production data, demo client): her 8 VESTA tasks show read-only, and the same 8 print on all three forms.\n\n**Technical:** `auth.service_tasks` joins `FORM_V2_FROZEN_KEYS` (data dictionary 3 \u2192 4). Its shared entry is now source context and also prints on the task guide. A new interview key, `shows`, lets a step display a fixed value read-only. `shared.plan.tasks_other` moves to `not_asked`.\n\n**To go live:** run `form-v2-pipeline.php --packet=SOC_AO --import --replace`, review and publish on `\/admin\/form-v2-publish`, then choose the new release on `\/admin\/form-v2-releases`. Visits already started keep their current paperwork.\n\nNot changed: the 3040's orientation task grid (A4) still asks about every task.","assets":[],"created_at":"2026-10-05T15:31:17-05:00","updated_at":"2026-10-05T15:31:17-05:00"},{"id":1015,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/102#issuecomment-1015","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/102","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":"**Decided and done (5 Oct 2026).** This follows from #89: the client's tasks are now VESTA's authorized list. We used both options, one on the screen and one on the paper.\n\n- **On screen: only the client's tasks.** The task guide step lists just the tasks the client is authorized for, each with what the task guide says it includes, so the supervisor goes over only those. Tasks that share a guide (transfer and ambulation, exercising and walking) appear as one line.\n- **On paper: the full guide, with the client's tasks marked.** The printed task guide is one fixed page, so nothing is cut from it. Each of the client's guides gets an X beside its heading. The marks were already measured on the page.\n\n**Checked on dev** (demo client, 8 tasks): the screen shows only her 8 tasks. The printed guide marks guides 01, 02, 05\/5A, 06\/07, 10, 11, 12 and 14.\n\n**Technical:** `task-guide.task_guide_reviewed` is now a target of the frozen `auth.service_tasks` entry, mapped to the guide codes. The step's `shows` carries each task's text as `option_info`.\n\nIt goes live with the same publish as #89.","assets":[],"created_at":"2026-10-05T15:31:17-05:00","updated_at":"2026-10-05T15:31:17-05:00"},{"id":1020,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/127#issuecomment-1020","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/127","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":"**Closing \u2014 committed and verified (2026-10-05).**\n\nThe pipeline is on `main` (`ef52232`, `745cfee`, `3bbf2db`): `scripts\/form-v2-pipeline.php`, `code\/form_v2_pipeline.inc.php`, `\/admin\/form-v2-publish`, and `scripts\/test-form-v2-pipeline-state.php` (25 passed, 0 failed).\n\nChecked against the issue:\n- **import \u2192 validate \u2192 publish \u2192 release \u2192 (activate):** one command, one transaction. Activation is refused on production and is #128's.\n- **Dry run by default, `--apply` to write:** yes. The dry run is a rehearsal that gets rolled back.\n- **Idempotent:** an unchanged file writes nothing, and unchanged content makes no new release.\n- **Same checks as the screens, refusals printed:** it uses the screens' own publishers and the #130 check.\n- **Interview publish, release assembly, single command:** all built.\n\nStill outside the chain, on purpose: packets (`import-form-packets.php --publish`).","assets":[],"created_at":"2026-10-05T15:41:54-05:00","updated_at":"2026-10-05T15:41:54-05:00"},{"id":1024,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/130#issuecomment-1024","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/130","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":"**Closing \u2014 committed and verified (2026-10-05).**\n\nOn `main` (`ef52232`, `745cfee`, `7e183f9`). `form_v2_publish_check()` in `code\/form_v2_review.inc.php` is the one implementation, and all three places call it:\n- the Explorer's Gaps tab (`backend\/formV2ExplorerGet.php`),\n- the CLI (`code\/form_v2_pipeline.inc.php`, #127),\n- the review page (`\/admin\/form-v2-publish`).\n\nSo the screen and the CLI cannot disagree.\n\nChecked against the issue:\n- **Every field filled, or blank for a recorded reason:** check 3.\n- **Every branch reachable:** check 5.\n- **No orphaned questions:** check 4.\n- **Every shared element has a ruling:** check 8. `test-form-v2-shared.php`: 202 passed, 0 failed.\n- **Every proof PDF renders:** check 9.\n- **Refuses on failure:** the publish commits only if every check passes.\n\nToday's run:\n- `test-form-v2-review.php`: 53 passed, 0 failed.\n- `test-form-v2-pipeline-state.php`: 25 passed, 0 failed.\n- `form-v2-pipeline.php --interview=SOC_AO_V2` rehearsal: all nine checks `ok`, and release `SOC_AO-20261005-5` would be published.","assets":[],"created_at":"2026-10-05T15:43:52-05:00","updated_at":"2026-10-05T15:43:52-05:00"},{"id":1045,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/108#issuecomment-1045","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/108","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":"**Done (5 Oct 2026).** The 3040's task questions now come from the client's VESTA tasks, the same list as the service plan, the coordination of care form and the task guide (#89, #102).\n\n**What the supervisor sees**\n- The 3040's task rows are asked only for the tasks the client is authorized for in VESTA. That covers how often each task is done and, when attendants are already working, how each attendant is doing with it.\n- At an orientation, only the frequency of each authorized task is asked, as before.\n- If VESTA lists no tasks, the task grid asks nothing.\n\n**What prints**\n- The rows for the client's tasks print as answered. The other rows on the 3040 print blank.\n\n**Checked on dev** (production data, demo client): her 8 VESTA tasks give 8 frequency questions at an orientation, and 32 questions with attendants working, down from 16 and 64.\n\n**Technical:** each `form.forms-3040.task_{row}_{freq,a,b,c}` question in `SOC_AO.json` is gated on `{\"contains\": [{\"field\": \"auth.service_tasks\"}, \"<task>\"]}`, ANDed with the existing orientation gate on the A\/B\/C ratings. The 3040's 16 rows match `FORM_FACT_SERVICE_TASK_DOMAIN` one to one, which `test-form-v2-workflow` pins. No schema or dictionary change. Commit 61655ab.\n\n**To go live:** it goes out with the same publish as #89: `form-v2-pipeline.php --packet=SOC_AO --import --replace`, review and publish on `\/admin\/form-v2-publish`, then choose the new release on `\/admin\/form-v2-releases`. Visits already started keep their current paperwork.\n\nNot changed: the limit on frequency per task is T3 (#103).","assets":[],"created_at":"2026-10-05T15:55:11-05:00","updated_at":"2026-10-05T15:55:11-05:00"},{"id":1050,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/84#issuecomment-1050","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/84","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":"Done in 5e24274. **Plan for emergencies** is now the step right after **Communication and emergency contacts**, before Health, home and needs. The other steps keep their order.\n\nChecked on dev: the interview reseeded cleanly, and a new Start of Care visit for the demo client shows the new order.\n\n**To go live:** `form-v2-pipeline.php --packet=SOC_AO --import --replace`, review and publish on `\/admin\/form-v2-publish`, then choose the release on `\/admin\/form-v2-releases`.\n\nNote: the customer's full section order (O2) may reorder the steps again.","assets":[],"created_at":"2026-10-05T15:57:32-05:00","updated_at":"2026-10-05T15:57:32-05:00"},{"id":1056,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/104#issuecomment-1056","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/104","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":"## Found and fixed\n\n**Cause: a hidden layer in the blank Task Guide PDF.** Our placement map and the render were not at fault.\n\nThe blank (`docs\/form-blanks\/task-guide.pdf`) came from a 2021 Adobe Illustrator file. It had two layers, and **\"Layer 1\" was switched off by default**. That hidden layer held an older copy of the page:\n\n- the **previous Legacy logo** (\"Health\/Hospice & PHC\/CBA Agency \u2013 *A Legacy of Caring*\"), in the same corner where the agency logo now prints;\n- a **second copy of the bottom line**, \"This program is only for the Client \u2013 NOT the entire family\", slightly offset so it looked doubled (and second copies of the section headings).\n\nWhether you saw it depended on the viewer. Our proof tooling (poppler) respects \"off\", so every proof looked clean. Apple's built-in PDF viewer and some print paths ignore it and draw the layer. The PDF tool that combines our answers with the blank (qpdf) carried the layer into every review and signed copy. Forcing the layer on reproduced exactly what the customer described.\n\n**Ruled out:** the placement map (proofs and a rebuild of the real review \u2192 signed path draw one logo and one bottom line); stamping twice at signing (the demo-day signed copy drew no logo, as designed); and the in-page form viewer.\n\n## Fix\n- Rebuilt the blank with the hidden layer's content removed and the layer settings dropped. Also removed a damaged page thumbnail of the old page and Illustrator's private data. qpdf now reports no errors; the old file had two damaged streams.\n- The visible page is **pixel-identical** to the old blank, and the text is unchanged, so every measured box stands. Only the fingerprint pin in `docs\/form-placements\/task-guide.json` changed (`e125925c\u2026` \u2192 `3aa2ceb5\u2026`).\n- The map moved onto the new paper and was published; deployed.\n- No other blank has a hidden layer.\n\nVisits prepared before the new release keep their pinned (old) paper, so only new visits get the fix.\n\nThe guard that keeps this from happening again is a separate action item.","assets":[],"created_at":"2026-10-05T16:09:53-05:00","updated_at":"2026-10-05T16:09:53-05:00"},{"id":1123,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/105#issuecomment-1123","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/105","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":"Done in 5e9e9f9.\n\n* Confirmed against the paper: 3B is `form.forms-3040.change_needed`, item 7 is `form.forms-3040.service_plan_adequate`.\n* Item 7 is no longer asked. It is a new shared element, `shared.service_plan_adequate`, worked out with a new derived op `map`: 3B Yes prints No on item 7, and 3B No prints Yes. If 3B is unanswered, item 7 prints blank.\n* **N\/A:** dropped, because it has no opposite. Once 3B is answered, item 7 always has an answer.\n* 3B's help now says it also answers item 7.\n* The Form Explorer shows item 7 as worked out from 3B.\n* Tests: `test-form-v2-shared` checks both directions on the real projection. It also checks that the map names every answer 3B offers.\n\n**To go live:** run `form-v2-pipeline.php --packet=SOC_AO --import --replace`, publish on `\/admin\/form-v2-publish`, then choose the release on `\/admin\/form-v2-releases`.","assets":[],"created_at":"2026-10-06T09:44:01-05:00","updated_at":"2026-10-06T09:44:01-05:00"},{"id":1124,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/106#issuecomment-1124","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/106","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":"Done in 5e9e9f9.\n\n* `ori_report_to_name` now fills from the agency name (`system.agency_legal_name`).\n* `ori_report_to_phone` now fills from the agency's **main** phone (`system.agency_phone`), as Frank's notes asked. It does not use the 24-hour line the consents print. No new setting was needed.\n* Both questions are removed from the SOC\/AO interview. The 3040 definition is now v6.\n* \"10-4\" was already recorded as the item number (G2).\n\n**To go live:** the same publish as #105. Set each agency's phone on Admin \u2192 Systems. If it is empty, the line prints blank.","assets":[],"created_at":"2026-10-06T09:44:01-05:00","updated_at":"2026-10-06T09:44:01-05:00"},{"id":1126,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/101#issuecomment-1126","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/101","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 in 5e9e9f9. I'm leaving this open until Jane confirms the list below.\n\n**How it works:** there is a new interview setting, `starts_as`. When a visit is started, the question already holds that answer, and the record's own value wins if it has one. The screen says under the question: \"Starts as Yes. Change it if that is not what happened.\" That way it stays clear the supervisor is attesting to it. A pre-set answer that is changed never counts as a difference from VESTA.\n\n**Starts as Yes:** these are the things the supervisor did.\n- Disaster plan: went over the agency policies\n- Task Guide: went over the program's scope, the safety instructions, and when to call the supervisor\n- Things You May Not Do: explained that services are only for the client\n- 3040 orientation: the client's health condition; tasks, schedule and safety; reporting events to the supervisor; the complaint procedure given and explained\n- PAS\/PHC and PCS consents: went over the rights\n- PAS\/PHC consent: client told in writing and in person what the attendant can and cannot do\n- Private Pay: attendant instructions; the Obligation of Client and terms\n- Advance directives: client received the agency's information\n\n**Left blank on purpose:** these record what the client decides or says, and a default there would be the agency answering for the client.\n- Consent to services (all three consents)\n- \"Has the client reviewed and approved the service plan\" (PAS\/PHC and Private Pay)\n- 2-1-1: \"Does the client understand them?\"\n- 3040: \"Has the attendant had HIV \/ hepatitis training?\" (a fact about the attendant, not something explained at the visit)\n\n**Jane:** please confirm both lists. Moving a question between them is a one-line change.\n\n**To go live:** the same publish as #105.","assets":[],"created_at":"2026-10-06T09:44:01-05:00","updated_at":"2026-10-06T09:44:01-05:00"},{"id":1130,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/88#issuecomment-1130","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/88","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":"**Confirmed:** the customer says this applies to every form, not only the service plan.\n\n**Done in b9d8709.** \"How often will the attendant be supervised?\" is no longer asked on any form. Each form now prints the answer itself:\n\n| Form | Prints |\n|---|---|\n| PAS service plan | \"Every __ Months \/ PRN\" box, with 12 |\n| Form 3040 | \"Q 12 month \/ PRN\" |\n| PCS consent | Other, with \"12 months \/ PRN\" written in (the paper only offers 6 months \/ Other) |\n| Private Pay agreement | Other, with \"12 months \/ PRN\" written in (the paper only offers 6 months \/ 60 days \/ Other) |\n\nHow it works: three new fixed shared values in `code\/form_v2_shared.inc.php` (`shared.supervision_frequency`, `shared.supervision_months`, `shared.supervision_frequency_other`). I removed the eight questions from `docs\/form-v2-interviews\/SOC_AO.json`. The service plan's \"Other\" frequency line is never ticked, so it is listed in `not_asked` and prints blank. Tests are in `test-form-v2-shared`.\n\n**To apply:** run `form-v2-pipeline.php --packet=SOC_AO --import --replace`. I've already done this on dev, and the rehearsal passes all nine checks. Then review and publish on `\/admin\/form-v2-publish`, and choose the release on `\/admin\/form-v2-releases`.","assets":[],"created_at":"2026-10-06T09:49:54-05:00","updated_at":"2026-10-06T09:49:54-05:00"},{"id":1133,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/93#issuecomment-1133","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/93","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":"**Decided (Charles, 6 Oct): over is a hard stop; under is allowed, with a warning and a flag on the review page.** Built.\n\n**Over the authorized hours**\n- A schedule change that takes the week over the authorized hours is **not saved**. The supervisor sees why under the day: \"The schedule comes to 22.00 hours a week, 1.00 more than the 21.00 hours authorized. Hours can be moved between days, but the week cannot go over\u2026\"\n- The check lists an over week against the schedule, so **the forms can't be generated** until it fits.\n- If VESTA's own schedule is already over, the visit still opens with it. Any change that brings the week down is accepted, so it can be fixed one day at a time.\n\n**Under the authorized hours**\n- Allowed. The running total beside \"Authorized: N hours a week\" says \"The schedule is X hours under. This is allowed, and the office will see it\u2026\"\n- On **Visit Review** the visit gets a yellow \"Schedule is under the authorized hours\" banner, and the list shows a badge saying \"Hours under authorized\".\n\nAn empty schedule (nothing entered yet) isn't flagged as under. Hours are compared in whole minutes against the pinned `auth.weekly_hours`.\n\nCode: `form_v2_schedule_week()` \/ `form_v2_schedule_total_status()` in `code\/form_v2_visit_rules.inc.php`, enforced in `form_v2_visit_save()` and `form_v2_visit_issues()`. I checked it on dev visit 19 (20 of 21 hours): +2 h was refused, +1 h (exactly 21) was saved and the flag cleared. Nothing needs publishing for this one. It's runtime code and applies on deploy.","assets":[],"created_at":"2026-10-06T10:06:53-05:00","updated_at":"2026-10-06T10:06:53-05:00"},{"id":1134,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/103#issuecomment-1134","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/103","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":"**Items 1 and 2 from the notes above are built.** Item 3 is still open.\n\n1. **FREQ is a drop-down: QD \u2014 Every day, QW \u2014 Every week, PRN \u2014 As needed.** Each task starts at its default from Frank's table: Laundry and Shopping start as QW, Escort as PRN, everything else as QD. The supervisor can change it. A row is still asked only when the task is in the client's VESTA list (#108). The paper prints the code (QD \/ QW \/ PRN) in the FREQ cell.\n2. **The blank \"other\" row.** \"Does the attendant do any other task that is not listed?\" is always asked, because it covers what VESTA doesn't list. Once a task is named, its frequency drop-down and A\/B\/C ratings appear. It prints on the paper's unlabelled row under \"Assist w. Self-Admin. Med\" (name on the line, code in FREQ, S\/U in the cells), checked on a rendered proof.\n3. **Still to ask the customer:** now that there are sensible defaults, do we still need to *refuse* QW on a daily task, or is the default enough? Nothing refuses it today.\n\nFiles: `docs\/forms\/forms-3040.json`, `docs\/form-placements\/forms-3040.json`, `docs\/form-v2-interviews\/SOC_AO.json`. A mark can now print a code of up to three capitals (it was one letter), with a fit check so a code can't overflow its cell. Imported to the dev drafts, and the publish rehearsal passes all nine checks. It goes out in the pending SOC_AO release with #88\/#101\/#105\/#106: publish on \/admin\/form-v2-publish, then choose the release on \/admin\/form-v2-releases.","assets":[],"created_at":"2026-10-06T10:06:53-05:00","updated_at":"2026-10-06T10:06:53-05:00"},{"id":1138,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/103#issuecomment-1138","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/103","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":"**Also fixed while I was in the grid:** choosing **N\/A** printed nothing on the 3040. That covered every A\/B\/C rating cell, including the new other row, plus items 4, 5, 8 and 9. The service plan's \"N\/A\" other-services box had the same problem. The maps now print \"N\/A\" in the rating cells and an X in the N\/A tick boxes, which I checked on a rendered proof. A test now fails any map whose N\/A box would print nothing. This goes out in the same pending SOC_AO release.","assets":[],"created_at":"2026-10-06T10:12:32-05:00","updated_at":"2026-10-06T10:12:32-05:00"},{"id":1139,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/113#issuecomment-1139","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/113","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":"Done in 7f9771e.\n\n**Cause.** On the PCS consent, the PAS\/PHC consent and the Private Pay agreement, the \"Witness 1\" \/ \"Witness 2\" lines were defined as typed text, even though the paper says the witnesses must *sign* there. Because they weren't signatures, no signing claimed the date beside them, so the interview asked for it. The H2076 already had witness signatures and wasn't affected.\n\n**Change.**\n- `witness_1` \/ `witness_2` on those three forms are now signature fields. Their boxes print a drawn signature and are sized like the release signature (checked on proofs of all three forms).\n- Each witness has their own signing line, and the date beside it is stamped when the witness taps Sign.\n- The 12 witness name and date questions are removed from the SOC\/AO interview. The witness gives their name when adopting a signature.\n- Pipeline fix: the interview import read the *published* placements, so a signing line added in the same import was invisible and its date came back as a question. `form_v2_signing_maps()` now prefers a placement's draft during import.\n\n**Until W4 (#114) is done**, the witness lines are owed on every visit. Staff use \"Record why\" on each one when no witness is needed. #114 is where witnesses become required only for an X signature.\n\n**To apply:** the rehearsal on dev passes all nine checks. Publish on `\/admin\/form-v2-publish`, then choose the release on `\/admin\/form-v2-releases`.","assets":[],"created_at":"2026-10-06T10:22:24-05:00","updated_at":"2026-10-06T10:22:24-05:00"},{"id":1141,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/114#issuecomment-1141","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/114","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":"Done in c9e7c29 (builds on #113, 7f9771e).\n\n**How it works.** Whether the client signs with an X is decided on the **signing screen**, when the client takes the pen. It is not an interview question.\n- Until the client has adopted a signature, each client line has a **Client signs with an X** button under its Sign button. It opens the client's adoption with a new **Signs with an X** box ticked. The box is also there when adopting from Sign.\n- **X:** the two witness lines become owed on every form that has them: the PAS\/PHC and PCS consents, Private Pay and the H2076. The witnesses give their name and draw a signature, and the date is stamped by their tap (#113).\n- **No X:** the witness lines say \"Only if the client signs with an X.\", are not counted toward finishing, and print blank. Staff no longer have to \"Record why\" on each one.\n- The choice belongs to that printing. If an answer changes and the forms are generated again, it is asked again.\n\n**Technical.**\n- New column `form_v2_visit_signer.signs_with_mark` (`migrations\/20261006_signer-signs-with-mark.sql`).\n- `form_v2_sign_plan()` makes a witness line apply only when the client's adoption carries the mark.\n- `form_v2_sign_adopt()` refuses the mark for anyone but the client.\n- Tests in `test-form-v2-sign-rules` and `test-form-v2-sign-state`.\n\n**Checked on dev.** SOC\/AO was published there, a visit was printed with private pay, and the client adopted an X: 28 \u2192 32 things to do, and the X buttons went away. Witness 1 adopted, signed and was stamped with the tap's time.\n\n**To apply:** `php scripts\/migrate.php --apply`, then publish #113's SOC\/AO release on `\/admin\/form-v2-publish` and choose it on `\/admin\/form-v2-releases`.","assets":[],"created_at":"2026-10-06T11:10:26-05:00","updated_at":"2026-10-06T11:10:26-05:00"},{"id":1153,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/82#issuecomment-1153","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/82","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 (commit 85a2957), not yet on production\n\nBuilt as proposed above, from a local copy of the national provider registry, not the live API.\n\n- **On the visit screen:** \"Who is the client's regular doctor?\" now has a **Find the doctor** button. Staff type part of the name. Results nearest the client's ZIP come first, and they can type a different ZIP or city. Each result shows name, specialty, address, phone and fax. Picking one fills the doctor's name, phone and the PAS service plan's **Physician Address**. Everything stays editable, and \"Not listed? Type it in the box above\" covers anyone missing.\n- **Who is searched:** Texas doctors (MD\/DO), nurse practitioners and physician assistants.\n- **What is kept:** the registry entry that was picked is recorded with the visit, encrypted.\n- **Tried on dev** with the latest weekly registry file. A pick fills all three boxes and saves.\n\n**To go live:** run the migration, load the registry once (`scripts\/import-npi.php --fetch --apply`, after which a weekly timer keeps it current), then republish SOC\/AO. Production needs outbound HTTPS to download.cms.gov for the import.\n\n**Still open:** if the customer keeps their own list of doctors, it can be loaded into the same table. Nothing is built for that yet.","assets":[],"created_at":"2026-10-06T11:42:10-05:00","updated_at":"2026-10-06T11:42:10-05:00"},{"id":1154,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/99#issuecomment-1154","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/99","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":"## Lookup built (commit 85a2957); \"on file\" prefill not yet\n\n- **On the visit screen:** the Emergency\/Disaster form's pharmacy question has a **Find the pharmacy** button. It searches the same local registry copy as the doctor lookup (#82), nearest the client first. A store's own name is searchable (\"CVS Pharmacy #1234\"), not only the company's legal name. Picking one fills the pharmacy name and phone.\n- **Known pharmacies:** pharmacies this agency has picked before are listed first and marked \"Used before\". With the name box empty, the list shows just those, so the drop-down of known pharmacies needs no separate list.\n- **Equipment supplier:** the DME supplier on the same form got the same lookup.\n\n**Not built:** saving the pharmacy on the client's record and prefilling future visits from it. As noted above, that should happen only after the office accepts the visit, and there is no office-acceptance step yet. In the meantime, the pick is recorded with the visit (encrypted), so it can be carried over once that step exists.","assets":[],"created_at":"2026-10-06T11:42:10-05:00","updated_at":"2026-10-06T11:42:10-05:00"},{"id":1156,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/137#issuecomment-1156","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/137","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 from the provider registry (commit 85a2957)\n\nThe directory is the same local registry copy as the doctor and pharmacy lookups (#82, #99). The national registry lists agencies with their phone **and fax** numbers, and a weekly update keeps it current, so there is no list for the office to maintain.\n\n**Where the lookup appears:**\n- **Coordination of Care:** each agency under \"Other care the client receives\" has a **Find the agency** button that fills the agency's name, phone and fax:\n  - skilled nursing and home health aide: home health and home care agencies;\n  - therapy: therapy clinics and home health agencies;\n  - dialysis: dialysis centers;\n  - adult day care: adult day care centers.\n- **Transfer form:** the agency the client is transferring from and the agency called. The form has no phone or fax boxes, so only the name is filled.\n\nAgencies this agency has picked before come first, marked \"Used before\". The contact person is still typed, because the registry doesn't list people at an agency.\n\n**For the customer:**\n1. Is putting it on both forms right?\n2. If they have their own list, it can be loaded into the same table alongside the registry.\n3. \"Home health\" here also includes in-home support agencies, where most PAS providers are registered. Please confirm that's what they want.","assets":[],"created_at":"2026-10-06T11:42:10-05:00","updated_at":"2026-10-06T11:42:10-05:00"},{"id":1162,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/93#issuecomment-1162","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/93","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":"Deployed to production on 6 Oct. A week over the authorized hours is refused, and a week under is allowed and flagged on Visit Review. Closing.","assets":[],"created_at":"2026-10-06T13:25:35-05:00","updated_at":"2026-10-06T13:25:35-05:00"},{"id":1165,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/140#issuecomment-1165","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/140","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 (not yet published).** The client's other care is now **one question**: a single list at the start of *Other care the client receives*. It fills the Coordination of Care and both pages of the service plan (`shared.other_services` in `code\/form_v2_shared.inc.php`). The choices are None, skilled nursing, home health aide, therapy, dialysis, adult day care (DAHS), medical equipment (DME), meals (HDM), emergency response, transportation and other.\n\n**What each paper ticks.** These need the customer's eye:\n- **Coordination of Care:** SN, HHA, therapy, dialysis, adult day care (as ADC) and other. It has no rows for equipment, meals, emergency response or transportation, so those don't print there. Each row is another agency's care with one contact, and its single Other row can't hold several services. \"None\" prints nothing ticked.\n- **Service plan, page 1** (\"Other Service Individual is Receiving\"): nursing and aide both tick **Skilled Home Health Aide**. Therapy, dialysis and equipment tick **Other**, and its \"Other (specify)\" line is asked. None ticks **None**.\n- **Service plan, page 2** (\"Other Services\"): meals tick **HDM** and None ticks **N\/A**. Anything without its own box ticks **Other**, and \"Other (specify name)\" is asked.\n- The adult day care's agency name is also page 2's DAHS name, so it's asked once.\n\nAll the follow-up questions now sit under the list on one step, and the overlap question is hidden when the answer is None. This also settles S5 (#90): no other services prints **None** and **N\/A**.\n\n**Item 4, the suspected mis-binding: not a fault.** Every interview version (1\u20138), the form definition and the placement bind `other_services_receiving` to page 1's \"Other Service Individual is Receiving\". \"What change is needed, and why?\" is the 3040's `change_needed_detail`. It's the question shown when `change_needed` = yes, on the *Attendants* step.\n\n**To ship:** the drafts are imported on dev and the publish rehearsal passes all nine checks. Next: review and publish on `\/admin\/form-v2-publish`, then choose the release on `\/admin\/form-v2-releases`.","assets":[],"created_at":"2026-10-06T13:44:18-05:00","updated_at":"2026-10-06T13:44:18-05:00"},{"id":1167,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/118#issuecomment-1167","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/118","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":"**Most of this was already in place. The gaps are now closed (not yet published).**\n\nAlready built (25 Sep):\n- The agency's details are kept per agency: legal name, toll-free and 24-hour numbers, administrator.\n- Each **branch office's** address, phone, fax and vendor number are kept per branch.\n- Both are maintained by a Superuser at **Superuser Tools \u2192 Systems** (*Branch Offices*), and they fill every form from the client's branch.\n- No interview question asks for any of them.\n\nDone today:\n- **A missing detail is reported.** Nothing marks these fields required, so a missing one printed blank without a word. The visit's check now lists each one that is not on file, with the forms it would print blank on and where to enter it (`form_v2_visit_office_missing()`). Like any check item, it can be skipped.\n- **The 3040's Vendor No. now reads the branch's number**, as the service plan already did. Before, it read the agency's, which is an NPI on file. Which number belongs on which form (vendor or contract) is still #117 (F1).\n\n**Waiting on the customer:**\n1. **The branch details need entering.** Every branch row is blank on the dev database; production not checked. Until they are entered, the service plan and the Coordination of Care print no office address, phone, fax or vendor number, and the check will say so.\n2. **Contract number** prints on no form today. If #117's answer is \"contract number on some forms\", it gets a column beside the vendor number then.\n\nH4 (#94, the coordinator per branch) can live on the same Branch Offices table when it's picked up.","assets":[],"created_at":"2026-10-06T13:44:18-05:00","updated_at":"2026-10-06T13:44:27-05:00"},{"id":1172,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/150#issuecomment-1172","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/150","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":"Done in f6e44d8.\n\n**Detection** \u2014 `code\/form_pdf_layers.inc.php`: a scan over qpdf's JSON for layers that start off (`\/D \/OFF`, or `\/BaseState \/OFF`) that the page still uses: a content `\/OC \u2026 BDC` span (including one through a membership dictionary or inside a form XObject), an image\/XObject `\/OC`, or an annotation `\/OC`. A `\/Thumb` is a warning, never a refusal. A layer that is on everywhere passes (`forms-3040` and `things-you-may-not-do` carry `\/OFF []`).\n\n**Where it is caught, all before publishing:**\n- `scripts\/test-form-blanks.php` walks every catalogue blank, plus a real-file fixture and the scan's other shapes. All 15 current blanks pass.\n- `form_v2_template_register()` refuses with a message in words, also for a fingerprint registered before this rule. It fails closed if qpdf is missing. `form-overlay-propose.php` prints the reason and registers nothing.\n- `form-pdf-proof.php` refuses to write the proof that would hide it.\n- The publish proofs (`form-v2-pipeline.php`, `\/admin\/form-v2-publish`) fail the form, so the release is not published.\n\nVerified against the pre-#104 Task Guide: every gate refused it, naming \"Layer 1\" on page 1.\n\n**Cleaning** \u2014 new `scripts\/form-blank-clean-layers.py` (PyMuPDF in venv) merges each page's content streams, cuts the off spans and the thumbnail, and refuses to write unless every page renders pixel-identical. It cleaned the old Task Guide with an identical result. The recipe is in `docs\/form-placements\/README.md`, under \"Hidden layers\".\n\nNote: `things-you-may-not-do.pdf` carries a page thumbnail, which is reported as a note only. I left it alone, because cleaning it changes the fingerprint and needs a re-pin.","assets":[],"created_at":"2026-10-06T13:55:29-05:00","updated_at":"2026-10-06T13:55:29-05:00"},{"id":1179,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/137#issuecomment-1179","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/137","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":"**Correction to question 2 above: struck.** The customer asked for the registry lookups so that they *don't* keep their own list. The doctor, pharmacy and agency lookups use only the national provider registry, and no customer list will be loaded.\n\nStill open for the customer:\n1. Is putting it on both forms (Coordination of Care and Transfer) right?\n3. \"Home health\" also includes in-home support agencies, where most PAS providers are registered. Is that what they want?","assets":[],"created_at":"2026-10-06T13:58:42-05:00","updated_at":"2026-10-06T13:58:42-05:00"},{"id":1184,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/145#issuecomment-1184","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/145","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":"Done in a3133cc.\n\nThe visit screen (`\/visit-v2`) now has a **Client details** button that opens a panel from the right. It shows what the V1 tray showed: status and branch, personal details, care team, authorizations, attendant schedules, assigned tasks, diagnosis, Medicaid eligibility and recent calendar, plus where the signed forms go (#83). Report flags and agency codes are left out, as they were in V1.\n\n- Served by the new `\/do\/formV2VisitClient`, gated like the other visit endpoints. The client is looked up from the visit, never from an ID in the request, and each view is logged as a PHI read.\n- The panel reloads every time it is opened, and has a Refresh button.\n- Built in `hh_client_sheet()` in `code\/hh_client_sheet.inc.php`.\n\nChecked in the browser on dev with the demo client.","assets":[],"created_at":"2026-10-06T14:27:10-05:00","updated_at":"2026-10-06T14:27:10-05:00"},{"id":1186,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/83#issuecomment-1186","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/83","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":"Done in a3133cc.\n\nA new step in the visit, **Sending the forms**, comes just before *Check the answers*. It asks for:\n- the client's email, or \"The client has no email\";\n- optionally, a family member or representative: name, relationship, and email and\/or mobile number.\n\nA representative is refused unless the supervisor confirms that the client chose this person. That confirmation is asked again whenever the person's details change.\n\n**Stored on the client record**, as asked: `hh_member.forms_contact_enc`, one encrypted package, plus who saved it and when (`migrations\/20261006-03_member-forms-contact.sql`). The next visit starts from what is on file, and it also shows in the Client details panel (#145).\n\n**Not an interview question, on purpose.** No form prints it, and the interview only asks what the forms carry. A V2 visit answer also never writes back to the client record. So this is an explicit save of the client's details through `\/do\/formV2VisitContact`. The save is logged without the values.\n\nRules are in `code\/hh_member_contact_rules.inc.php` and tested standalone by `scripts\/test-member-contact-rules.php`.\n\n**Still to do:** sending the forms by email or text is not built yet.\n\n**To apply on production:** `php scripts\/migrate.php --apply`","assets":[],"created_at":"2026-10-06T14:27:10-05:00","updated_at":"2026-10-06T14:27:10-05:00"},{"id":1190,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/111#issuecomment-1190","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/111","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 in ce30deb. On dev, not published yet.\n\n**What the forms actually have.** No signature line on the SOC\/AO forms is only for a representative: every client line reads \"Client \/ Authorized Agent\". The \"signing for the client\" content is two typed lines on both consent forms and the Private Pay agreement: the signer's authority (`shared.release.authority`), and why the client cannot sign (`shared.consent.unable_to_sign_reason`).\n\n**What changed**\n- The interview asks **\"Is the client signing the forms themselves?\"** (`visit.client_signs`). It starts at Yes, and the supervisor can change it.\n- The authority and the reason are asked only when the answer is **No**. On Yes they are hidden, and a hidden answer is never printed, so those lines stay blank.\n- Signing must agree with the answer. On Yes, adopting a signature as \"someone signing for the client\" is refused. On No, adopting as the client is refused. The adoption dialog offers only the matching choice. Visits prepared before this release are unaffected.\n- Why this is in the interview rather than at signing, as the X was in #114: these lines are printed before anyone signs.\n- Fixed along the way: loading the interview file silently dropped any question that no form prints. It now keeps the ones the file asks for.\n\n**Checked:** the related tests pass, including new ones for the signing rule and the question loading. The SOC\/AO publish rehearsal shows one new question and two now conditional, and passes all nine checks. Not tested yet: clicking through it in a browser, and refusal of a contradicting signature at the database level. Only the underlying rule has a test.\n\n**To make it live:** review and publish on `\/admin\/form-v2-publish?interview=SOC_AO_V2`, then choose the release on `\/admin\/form-v2-releases`. This publish also carries the #140 and #118 interview changes.\n\n**Open point:** the question starts at Yes, which treats \"who is signing\" as something the supervisor observes rather than a decision the client makes. A wrong Yes is caught at signing. If it should start blank instead, that is a one-line change.","assets":[],"created_at":"2026-10-06T14:41:03-05:00","updated_at":"2026-10-06T14:41:03-05:00"},{"id":1194,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/111#issuecomment-1194","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/111","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":"**Open point settled (owner, 6 Oct 2026).** \"Is the client signing the forms themselves?\" starts at **Yes**. **No** means someone else signs for the client. There is no third answer: a client who refuses to sign has no interview, so refusal is never a route through it.\n\nThe build already works this way, so no code changed. The ruling is recorded in `docs\/FormsV2Plan.md`, the interviews README and the Changelog (96356f4).\n\nWhat is left is to publish the release on `\/admin\/form-v2-publish?interview=SOC_AO_V2` and choose it for each agency on `\/admin\/form-v2-releases`.","assets":[],"created_at":"2026-10-06T14:43:16-05:00","updated_at":"2026-10-06T14:43:16-05:00"},{"id":1197,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/111#issuecomment-1197","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/111","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":"Live: deployed, and the SOC\/AO release is published and chosen for each agency. A Start of Care visit prepared from now on asks \"Is the client signing the forms themselves?\" (starts at Yes). Visits prepared earlier keep their old interview. Closing.","assets":[],"created_at":"2026-10-06T14:45:48-05:00","updated_at":"2026-10-06T14:45:48-05:00"},{"id":1199,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/143#issuecomment-1199","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/143","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":"## Audit of PHI read logging across Forms V2 (2026-10-06)\n\nChecked every `backend\/formV2Visit*.php` endpoint and the three V2 pages for whether a response that carries client data records `audit_phi_view()` (or an equivalent).\n\n### Already in place\n| Path | Records |\n|---|---|\n| `\/visits-v2` (preset client, open-visit list) | `phi.member.view` |\n| `\/visits-v2-review` (one visit, list) | `phi.member.view` |\n| `formV2VisitOpen` (the full visit payload: every answer) | `phi.member.view` |\n| `formV2VisitClient`, `formV2VisitContact` (read), `formV2VisitMemberSearch` | `phi.member.view` |\n| `formV2VisitSignState` | `phi.member.view` |\n| `formV2VisitDocument` (PDF open\/download) | `phi.document.open` inside `document_version_stream()`, so it can't be skipped |\n| Prepare, Print (artifact create), Abandon, sign adopt\/tap\/withdraw\/finish | `data.form_v2.*` write events carrying `fk_hh_member` |\n| `formV2VisitBlank`, `formV2TemplatePage` | none needed: a blank form carries no client |\n| `\/visit-v2` page | renders no client data server-side; it loads everything through `formV2VisitOpen` |\n\n### Gaps\n1. **`formV2VisitSave` on a conflict**: returns `current`, the decrypted stored values of the answers someone else changed (`form_v2_visit.inc.php:703-707`). This is a PHI read with no view event. It's a rare path, but it's a real one.\n2. **`formV2VisitSign`, `formV2VisitSignAdopt`, `formV2VisitSignFinish`**: each returns the full `form_v2_sign_view()`: the client's name, every signer's and representative's name, and decrypted refusal reasons. `SignState` logs the identical payload as a PHI view; these three don't. A successful write leaves a `data.form_v2.sign.*` event with `fk_hh_member`, but two paths leave nothing at all:\n   - a **replayed** request (idempotent retry), which returns the view without writing;\n   - a **failed** `SignFinish`, which still returns the view (`formV2VisitSignFinish.php`: the view is built before the `ok` check).\n\n### Judgment calls (low; recommend logging anyway for consistency)\n3. **`formV2VisitCheck`**: returns issues and progress. The messages are mostly question labels, but the schedule-step messages echo the client's hours.\n4. **`formV2VisitPlan`**: decrypts the client's facts (`form_v2_visit_plan()` documents `facts` as PHI) and returns which forms that client needs, which is derived from their program, language and so on. It takes a `pk_hh_member` straight from the request (scope-checked).\n5. **`formV2VisitLookup`**: when no `near` is sent, returns the client's ZIP from the visit as `near`.\n\n### Proposed fix\nAdd `audit_phi_view('<endpoint>', ['pk_hh_member' => \u2026, 'fk_system' => \u2026, 'pk_form_v2_visit' => \u2026])` to items 1\u20135, placed only on the branches that return the data, matching `SignState`\/`Open`. A guard test in the style of `test-backend-auth-guards.php` (every `formV2Visit*` endpoint either calls `audit_phi_view` or is listed as carrying no PHI, with the reason) would stop a new endpoint from shipping without one.","assets":[],"created_at":"2026-10-06T14:51:15-05:00","updated_at":"2026-10-06T14:51:15-05:00"},{"id":1200,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/143#issuecomment-1200","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/143","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":"Fixed in 61d7518 (committed, not yet pushed).\n\nAll five items from the audit above now record `phi.member.view`, each only on the branch that returns the data:\n- `formV2VisitSave`: on a conflict that returns `current`, with the number of answers returned.\n- `formV2VisitSign`, `SignAdopt`, `SignFinish`: whenever the signing view goes back, including replayed requests and a failed finish.\n- `formV2VisitCheck`, `formV2VisitPlan`: on success.\n- `formV2VisitLookup`: only when `near` is the client's ZIP, not a place the supervisor typed.\n\n**Guard:** `scripts\/test-form-v2-phi-audit.php`. Every `backend\/formV2Visit*.php` must call `audit_phi_view()` or be listed with the reason it carries no PHI. Listed today: Abandon, Prepare, Print, Blank, and Document, which is logged by `document_version_stream()`. Any endpoint that calls a PHI source (`form_v2_sign_view`, `form_v2_visit_payload`, `form_v2_visit_values`, `form_v2_visit_check`, `form_v2_visit_plan`, `db_decrypt`, \u2026) must log, whether or not it is listed. Run against the pre-fix code, it fails on all seven files; it passes now. `test-backend-auth-guards.php` still passes.\n\nThe test proves a call is present, not that it sits on the right branch; that part is still a review question.\n\nLogged in `docs\/Changelog.md`. No user-facing change, so `docs\/UserChangelog.md` doesn't need an entry.","assets":[],"created_at":"2026-10-06T14:55:22-05:00","updated_at":"2026-10-06T14:55:22-05:00"},{"id":1204,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/149#issuecomment-1204","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/149","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":"Done in a951d22.\n\n- **Import:** `form-v2-pipeline.php` runs `import-form-packets.php --only={PACKET}` before anything else, because the packet decides which forms are imported. The importer is now idempotent. A file that matches the draft, or the published version when there is no draft, writes nothing, and a dry run reports \"unchanged\" or \"would update\". The run and the interview import read the packet **about to be** published (`form_packet_pending()`, `form_v2_packet_form_codes(\u2026, $pending)`). A form the file adds is therefore imported, placed and pinned in the same run. A dry run also lists forms named only in the file.\n- **Publish:** the order is forms \u2192 **packet** \u2192 maps \u2192 interview \u2192 release, all in one transaction. The packet goes through `form_packet_validate_definition()` with `form_packet_validation_ctx($db, $pk, true)`, so the install-wide item-key rule is still checked across every other published packet. It is written by `form_packet_publish_draft()`. A refusal stops the release, and nothing is kept.\n- **Check:** new pure `form_packet_def_diff()` covers forms added or removed, lines added, removed or renamed, required pages, conditions, choices and order. It feeds the packet step's changes and a new `packet_diff`, measured against the last release's pin. `\/admin\/form-v2-publish` shows it under \"What changed \u2192 The visit type\".\n- **Release:** the packet pin is part of the manifest, so a packet change alone makes a new release and an unchanged packet does not.\n\nTests: `test-form-packet` (diff) and `test-form-v2-pipeline-state`. The state test covers three cases. A draft identical to the published packet is not a change. A changed draft publishes in order into a new release, and the rehearsal keeps nothing. A draft the gate refuses stops the release. All form V2 tests pass. No schema change.","assets":[],"created_at":"2026-10-06T15:07:39-05:00","updated_at":"2026-10-06T15:07:39-05:00"},{"id":1278,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/82#issuecomment-1278","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/82","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":"**Live on production. Closing.** \"Find the doctor\" fills the doctor's name, phone and the service plan's Physician Address from the local copy of the national provider registry. The open question is settled: the customer asked for this lookup so they would not have to keep their own list of doctors, so no customer list will be loaded (same ruling as #137).","assets":[],"created_at":"2026-10-07T10:35:44-05:00","updated_at":"2026-10-07T10:35:44-05:00"},{"id":1281,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/77#issuecomment-1281","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/77","user":{"id":3,"login":"connect-bot","login_name":"","source_id":0,"full_name":"","email":"connect-bot@noreply.www-s01.apinet.com","avatar_url":"https:\/\/www-s01.apinet.com\/codeforge\/avatars\/68a2723f7ad70dee2e1415be7488d84b","html_url":"https:\/\/www-s01.apinet.com\/codeforge\/connect-bot","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2026-10-01T08:49:35-05: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":"connect-bot"},"original_author":"","original_author_id":0,"body":"**Charles W.** _(via Connect)_\n<!-- connect:user=1 -->\n\nStandardize on \"Client Name\". When there are shared questions or answers, show the fuller version if it's one of the options. Male instead of M. Service tasks show \"1 - Bathing \/ Ba\u00f1ar\". Emergency priority class shows the paragraph.","assets":[],"created_at":"2026-10-07T10:49:46-05:00","updated_at":"2026-10-07T10:49:46-05:00"}]}