Workflow reconciliation (see previous commit) showed the 20261022
state variable really stores person identity under driver{i}ID /
driver{i}Phonenumber (x2), while the API get_info group keys
(sfzmhm{i}/sjhm{i}) have zero references in any workflow version -
the legacy group read always returned empty for workflow-produced data.
- registry: +4 keys (driver1/2ID, driver1/2Phonenumber) in
human1/human2 groups, SENSITIVE, documented as synonymous with
sfzmhm{i}/sjhm{i}; 24 -> 28 specs
- driver{i}License deliberately NOT registered: the sandbox reads
state.hphm{i} and only renames the output for confirmation prompts -
it is not a state key, set_info rejects it as unknown (workflow
never consumes it)
- intentional diff documented: acdhuman1/2 group output now includes
the driver keys (legacy FastGPT output did not) - fixes the legacy
'workflow person data unreadable by group' gap; synonym merging
(driver1ID vs sfzmhm1) deferred pending caller confirmation
- tests: registry size 28, driver keys present with sensitive level,
License alias excluded
Verified: 230 unit tests
Reconciled the field registry against workflow/20261022 (synced with
main@c7ca781) and historical versions 20250419-20261021:
- form six keys match the workflow form variable (bNJkeXot) and the
更新表单 whitelist semantics exactly
- acd business keys originate from the 20250419 extraction schema
(dropped by the workflow since 20251015, kept as the API contract)
- person group keys (xm1/sfzmwh1/sjwh1/csbw1...) exist in no workflow
version - they are the API server's own contract
- the form<->business key mapping is migration-new semantics bridging
both sides, fixed by bidirectional tests
Finding: workflow 20261022 state uses driver1ID/driver1License/
driver1Phonenumber naming, which never matched the API get_info group
keys - existing behavior read empty; recorded in the audit backlog to
confirm which naming live callers actually use
- fields_registry: FORM_TO_BUSINESS_KEY bidirectional mapping between
the graph's six form keys (has_injury...) and the acd business keys
(ywrysw...); bjrjs/ywmtc have no form source (set_info only);
business_patch_from_form maps graph diffs to whitelisted business keys
and filters internal/unknown keys
- app_service: chat injection now maps repository business keys back to
form keys; both complete() and stream() write back field diffs
(FormUpdate events captured in stream, closing the skeleton gap);
form keys never leak into the business repository
- docs/assignment6-compat.md: mapping table documented, stream write-back
backlog item resolved
- tests: mapping coverage, write-back mapping end-to-end, reverse
mapping injection (bjrjs/ywmtc excluded), stream FormUpdate write-back
Verified: 205 unit tests
- fields_registry: 24 business keys in acd/human1/human2 groups with
value_type, writable and SensitiveLevel metadata; strict bool/int
parsing (no bool('0') trap); INTERNAL_FIELD_KEYS protection list
- repository: SessionRepository protocol + InMemorySessionRepository
(idempotent delete; PostgreSQL swap-in is assignment 7)
- AccidentAppService: chat/set_info/get_info/delete_session share one
business state - chat injects latest repository fields into the graph
and writes back validated field diffs; set/get/delete make zero LLM
calls and zero helper conversations (includeInputInfo accepted but
unused); unknown get keys keep the '' JSON-empty-string contract,
unknown set keys are rejected by whitelist
- ChatInput.injected_fields neutral contract extension; LangGraphBackend
merges injected fields into graph input (set_info visible next chat)
- endpoints: thin layer - langgraph mode routes business state through
the app service (fastgpt mode keeps the legacy path); delete cleans
repository + graph checkpoint, idempotent
- tests: registry completeness (sfzmwh/sjwh/csbw included), app service
combos with LLM-call spy, HTTP acceptance flow (set -> get -> chat ->
groups -> delete -> no leak, idempotent re-delete)
- docs/assignment6-compat.md: behavior diff list vs FastGPT status quo
and the audit backlog (arbitrary set_info key usage, stream formUpdate
write-back, sensitive-field display boundary)
Verified: 200 unit tests (172 existing + 28 new)