Files
shanxia2.0/docs/superpowers/plans/2026-10-27-child-data-differential-save.md
T

31 KiB

Child Data Differential Save Implementation Plan

For agentic workers: Use test-driven-development and requesting-code-review; independently owned domains may use dispatching-parallel-agents. Preserve current working tree edits.

Goal: Stop ordinary saves from rebuilding child identities across backend, Web/H5 and miniprogram.

Architecture: Domain-specific scoped reconciliation, existing-row updates, explicit deletion guards. Natural-key relation sets are synchronized independently; entity collections preserve server IDs. Missing collections remain unchanged. No schema migration or historical data rewrite by default.

Tech Stack: Python/FastAPI/SQLAlchemy/Pydantic; Vue/TypeScript; uni-app JavaScript.

Tasks

  • Logistics: add failing identity/partial-write/reference-guard tests, fix backend/app/services/pl_plan_stop_service.py, pl_plan_service.py, pl_plan_contract_gap.py, pl_brand_archive.py, pl_feedback_brand_qty.py, pl_personnel_service.py; schemas/API and related Web/H5/native clients as needed. Verify existing plan/stop/brand/feedback tests plus new tests.
  • CRM: failing roundtrip/omission/reference tests; fix backend/app/crud/crm/{quote,quote_product,contract,contract_product}.py, corresponding schemas/routes and desktop/mobile clients. Preserve tiers and IDs; reject deleting referenced contract lines. Run CRM regression tests and frontend identity tests.
  • Reimburse: failing diff and in-flight-node tests; fix backend/app/services/bx/{reimburse,workflow}.py, schemas/routes and Web/H5/miniprogram expense/workflow forms. Verify missing-list behavior and safe copying.
  • System/duty: failing tests for independent role/post sets, stable relation IDs, role menu/scopes and assigned duty people; replace full-delete save routines in backend/app/crud/{user,role}.py and backend/app/services/duty_schedule.py. Retain grabs and validate ownership.
  • Integration review: inspect all remaining ordinary-save full replacements, inspect frontend payloads, check field consistency, targeted backend tests, frontend tests/typecheck/build and native scripts. Repair regressions attributable to this change.
  • Independent review and graph refresh: review identity security, lifecycle/data-loss edges; update backend/frontend/miniprogram/root graph where changed; summarize changes and actual verification limits.

Test cases required in every applicable domain

existing A+B -> unchanged A+B: both IDs and creation metadata unchanged
existing A+B -> updated A + B + new C: only C receives a new ID
existing A+B -> A: B soft-deleted only if no downstream references
collection omitted: no collection write; collection []: explicit deletion rules
foreign/duplicate ID: rejection before applying any mutation
edit load-submit retains detail IDs; copying removes detail IDs

Execution constraints

Current checkout contains user changes needed for current mobile behavior. Work in place without resetting, stashing or bulk committing those changes. Agents own disjoint domains; shared changes must be coordinated. Do not connect to business databases for tests. No production data repair or deployment.

Review and verification notes

  • CRM received independent review from the reimburse-domain agent; system/duty received independent review from the CRM-domain agent. Review findings about nullable patches, tier ordering, target-tenant validation and user-creation atomicity were fixed with regression tests.
  • The logistics review additionally covers restored stop identities, ambiguous product references, archive-field preservation and partial-update totals.
  • Tests use isolated SQLite databases or mocks. The integration pytest runner explicitly rejects every PyMySQL connection, including a pre-existing public pound-QR test that otherwise connects to the configured business database.
  • No schema migration, production deployment, or historical-data repair is included. Existing bad references are not silently rebound.
  • The repository-required python3 scripts/check_field_consistency.py was attempted, but that script is absent (also absent from the repository file search).
  • Existing unrelated failures were checked against the starting-worktree patch: pl_io_order_service.py, schemas/pl/base_data.py, recharge list_applies, and four CRM mobile detail pages were unchanged by this task. Do not conflate these failures with the new child-identity regressions.
  • Full native packaging/device verification requires HBuilderX/WeChat tooling; this task executes native payload logic tests, not a device acceptance test.

Final verification (2026-10-27)

  • New backend child-differential suites: 103 cases passed across isolated tests (system 11, duty 7, CRM 23, reimburse/workflow 24, logistics 38). The integration run also passes all of these cases.
  • Web/H5/native form execution suites: 25 passed; native driver feedback identity: 1 passed. Logistics broader frontend suite: 56 passed.
  • Final Web production build: passed (pnpm build, 49.57 seconds).
  • Final complete backend run with MySQL connections prohibited: 1,355 passed, 6 failed. Outstanding items are the unchanged IO enrichment mock, the pre-existing deleted SQL snapshot test, the vehicle-create fixture missing trailerNo, two recharge-list mocks missing recharge_type, and the public pound-QR integration test requiring a business database connection. These are outside the child-save fix; no business DB was accessed to force them to pass.
  • Broader Web scripts: 1,312 passed, 11 failed in unchanged mobile CRM detail pages/tests. Full vue-tsc --noEmit remains blocked by repository-wide diagnostics; production bundling succeeds but this is not a clean typecheck claim.
  • Backend, web-admin, miniprogram and root graphify update completed. The generated JSON and reports are current; HTML visualization was skipped by graphify's size limit.
  • Final independent logistics review found no remaining blockers in the six reviewed identity/partial-save cases. Database-engine concurrency and real-device UI acceptance were not exercised by SQLite/payload tests.

Follow-up audit and mandatory rule (2026-10-27)

The repository root AGENTS.md now requires differential child saves across backend, Web/H5 and miniprogram, including imports that update existing data. It prohibits physical/soft delete-all followed by reinsertion, and client-side delete/create workarounds. It specifies identity preservation, omitted/empty semantics, prevalidation, reference protection, atomic writes and regression coverage.

The follow-up re-read all 378 Python application files with mutation/call-site searches and an AST candidate scan, then traced the candidate saves and relevant Web/H5/native callers. Maintenance scripts were separately searched. Keyword matches alone were not treated as bugs.

Confirmed ordinary-save omissions, now fixed:

  1. backend/app/crud/crm/product.py — product brands/aliases could recreate rows for missing or invalid IDs. Both collections are prevalidated before parent/child mutation; unique legacy names can reuse rows, invalid/duplicate IDs are rejected, and omitted status/order fields are preserved.
  2. web-admin/src/components/business/pl-plan-form-dialog/index.vue — changing a contract set cleared all stop products, including when merely adding a contract. Real watcher tests now verify that retained contracts retain their product objects/IDs/archive fields; only rows explicitly tied to removed contracts are removed. Unidentified legacy rows are retained for explicit reconciliation.
  3. backend/app/services/pl_cert_service.py — unknown or omitted certificate IDs recreated rows. The service now validates the complete request first, reuses only an unambiguous legacy business key, and preserves existing identity/status/creation data. Partial updates preserve omitted certificate fields; explicit null still clears nullable fields.

Classification and remaining findings:

  • Parent deletion, cancellation and creation of a genuinely new workflow version were distinguished from editing the same child set. revoke_regeneratable_dibang_for_transport is currently called by plan cancellation, despite its stale re-arrangement-oriented comment. Inventory re-posting on an explicit archive adjustment is a derived-ledger lifecycle; this audit did not redesign it.
  • Unused all-child soft-delete helpers in quote/contract products and _clear_legacy_side_contracts have no active application callers. They must not be reintroduced into ordinary save paths.
  • A separate active defect remains in the legacy plan branch with no load stop: sync_dibang_for_transport -> _sync_transport_inventory_links inserts derived inventory/links and adds monthly quantities without reusing existing links. Repeated arrangements can duplicate these records. This is repeated insertion, not the delete-all/reinsert pattern; no live database was queried to establish affected records and this branch was not changed here.
  • Three standalone quote-product endpoints still have argument/signature mismatches (missing quote_id on insert; unsupported tenant_no on update/delete), and the update payload also lacks exclude_unset. They were recorded separately from this audit's save-pattern repairs and remain unchanged.
  • Current BX clients return detail IDs. Unsupported old clients that omit existing detail IDs remain a compatibility risk: a missing ID denotes a new line; the API cannot infer every user's intent. The new rule requires edit clients to preserve IDs.

Follow-up verification: 146 isolated backend differential-save cases and 87 Web/H5/native payload/watcher cases passed; Web production build passed (41.13 seconds). MySQL connections were explicitly blocked in the backend verification runner. The earlier full-repository failures/typecheck limitations remain recorded above; no deployment or historical data repair occurred.

Historical migration entry points were also hardened in this follow-up: migrate_crm_product.py, migrate_crm_product_category.py, migrate_dibang_data.py and migrate_bx_data.py no longer execute clear-before-import SQL. The legacy CLI clear flags are explicitly rejected immediately after argument parsing; library entry points reject clear flags before any connection/read/write. BX now defaults to preserving workflow definitions, with its old --no-replace-workflow flag accepted for compatibility. The original non-clearing migration behavior remains unchanged; repeatability of the legacy dibang importer is not claimed. Pure AST/FakeEngine tests verify the rejection boundaries and non-clearing compatibility: 27 passed. No migration module/main was executed against a database.

Third audit fixes approved by the user (2026-10-27)

Scope is the current checkout only. The user explicitly accepts the legacy transportation adjustment that voids the old IO order and creates a replacement; leave that behavior intact. They authorize fixing archive inventory replacement, missing-detail-ID replacement, and repeated legacy weighbridge insertion. This supersedes the earlier classification of archive re-posting as an accepted lifecycle.

  • Inventory: add isolated regressions for identical archive resubmission, quantity/price edits, removed/new posting keys, multi-stop lines, tenant isolation and cancellation. Change backend/app/services/pl_inventory_service.py to reconcile existing postings and apply only inventory differences, preserving retained IDs/creation metadata. Do not infer a false line identity when the existing schema cannot identify a unique source.
  • Missing IDs: add regressions before changing backend/app/services/pl_plan_stop_service.py and backend/app/services/bx/reimburse.py. Resolve only unique existing business keys within the active parent/tenant scope, reserve explicit IDs, reject ambiguous requests before mutation, and retain omitted fields. New rows and explicit removals remain supported; existing Web/H5/native ID payloads remain compatible.
  • Weighbridge: add a real SQLite repeated-arrangement regression before changing backend/app/services/pl_dibang_bridge_service.py. Reuse valid legacy links/inventory, apply monthly quantity deltas, protect weighed records, and reject ambiguous/broken historical links rather than automatically repairing them.
  • Verify current client identity suites, focused backend regressions, independent review and field-consistency check availability. Refresh changed backend/Web/native graphs and the root graph. Never access business databases; no historical repair, deployment, branch switch or bulk commit.

Acceptance examples: identical archive keeps all posting IDs and stock; same legacy arrangement twice produces one link/IO and the original monthly quantity; a uniquely identifiable detail without an ID retains its old ID; ambiguous missing IDs fail without writes; an existing explicit row plus a genuinely new row still inserts only the new row.

Third-audit implementation and verification

  • PL missing-identity regressions initially failed 10 cases. Independent review found an additional draft case: absent detail/link IDs must not turn an already-linked delivery product into a pending row. Two additional failing cases were reproduced and fixed; the final new suite contains 18 cases, including linked/pending ambiguity rejection. The reviewer independently verified preserved identity and no removed row.
  • BX regressions initially failed 8 cases. The service now matches only a unique remaining expense key after reserving explicit IDs; omitted remark/date fields are preserved and explicit null clears them. Web/H5 and native expense forms send null for explicitly cleared dates (4 frontend cases failed before the fix). Independent review passed with 35 backend and 15 actual frontend-handler cases.
  • Legacy weighbridge regressions initially failed 17 cases. Review added failing stale-session/month-contribution-total cases; locked reads now refresh state, products lock in sorted order before monthly-bucket lookup, and all old contributions are checked before mutation. Related new/existing weighbridge suites pass 47 cases. Weighed records retain their actual quantities and feedback; changed protected input is rejected.
  • Inventory regressions initially failed 13 cases; added failing pending-brand, API-lock and outbound-price cases drove the remaining fixes. The final new inventory suite has 20 passing cases. Postings aggregate by plan/product/brand/direction, preserving existing identities and creation time; quantities and recorded amounts change by net delta. Multiple stop prices use a weighted display price while retaining summed amounts. Existing ambiguous same-key historical rows or missing ledgers return 409 without automatic repair. API locking refreshes plan/source state before cancellation/archive decisions; direct service entry retains pending caller changes. No-op preserves stock-after snapshots; changed historical rows adjust their own snapshot, without rewriting later rows or retrospectively revaluing legacy stock.
  • Final root integration run: 276 related backend cases passed with all PyMySQL connection attempts blocked (BX suites, PL child/stop/mobile identity, weighbridge, inventory, archive stops/brands and cancellation). Independent cross-review found no remaining blockers in the modified paths.
  • Current-source Web/H5/native handler suites: PL 19, native PL 1, BX 15, all passed. Web production build passed in 45.57 seconds. Existing build warnings remain (component-name conflict and large bundles); this does not claim a clean repository-wide typecheck or native device build.
  • Broader mobile metadata check: 119 passed, 1 pre-existing failure because docs/sql/20261023_mobile_plan_stop_product_meta.sql is absent in the starting worktree. The required field-consistency command was attempted again, but scripts/check_field_consistency.py is also absent. Neither file was recreated as an unrelated change.
  • No schema change, historical repair, deployment or database connection. MySQL lock SQL/order is covered by isolated tests; live concurrent MySQL behavior has not been exercised. The explicitly accepted IO void/recreate lifecycle remains unchanged and is documented as a narrow exception in AGENTS.md.

Fourth audit fixes approved by the user (2026-10-27)

The user authorized continuing all four newly confirmed residual fixes on the current branch. Preserve the existing worktree and accepted IO replacement lifecycle. No historical data repair or production database access is involved.

  • Main plan products: reproduce the actual draft update API accepting identical product rows without IDs and growing total rows 1→2→3; use one shared preflight/persistence resolution that preserves uniquely identifiable old rows, creation metadata and omitted actual/archive fields. Reserve explicit identities first; reject ambiguous legacy matches before any mutation. Files: backend/app/api/pl/plan.py, backend/app/services/pl_plan_service.py, backend/app/services/pl_plan_stop_service.py, new identity regression tests.
  • Delivery parents: reproduce missing parent and child IDs replacing a delivery and its products. Resolve only a unique parent using reliable submitted business identity or owned child IDs; never guess by array position/sequence. Preserve nested rows and explicit-ID security checks; truly new delivery rows and deliberate deletion remain supported. Use the same stop-service preparation for preflight and persistence; add parent/child, partial-field and cross-scope regressions.
  • Stop weighbridge dangling history: reproduce a link referencing a missing/deleted inventory and monthly contribution 5→10. Prevalidate and reject invalid historical links without soft deletion, new inventory, rebinding or contribution changes. Files: backend/app/services/pl_dibang_bridge_service.py, new isolated stop-bridge tests.
  • Stop weighbridge repeated product: reproduce two accepted stop rows sharing one plan product with quantities 5 and 3; first call creates duplicate links and repeat changes the monthly total 8→6. Aggregate compatible stop quantities by the bridge's stable key before reconciliation, keep one link/inventory and contribution 8 across retries, reject inconsistent metadata or ambiguous historical links. Validate the entire multi-stop batch before writes and exercise actual autoflush=False behavior, existing feedback and locks.
  • Verify current Web/H5/native edit/copy/save-response identity flow, focused backend integration and independent review. Update graphs for changed projects and root; record actual verification and limits. No branch switch, reset, bulk commit or deployment.

Fourth-audit implementation and verification

  • Main product and delivery parent resolution now reserves explicit IDs and reuses only unambiguous active identities within the current tenant/plan. Preflight and persistence share prepared IDs, including new main-product clientKey links and new stop IDs. Missing fields preserve existing business data; ambiguous identity, duplicate IDs and downstream-protected removals fail before writes. The new actual-API/SQLite suite contains 36 passing cases; initial reproduction had 13 failing cases.
  • Multi-stop weighbridge now aggregates compatible stop rows by plan-product ID before syncing. Quantities 5 + 3 remain 8 on repeated saves, with stable link/IO IDs and feedback. Existing positive quantity changed to explicit zero reverses its contribution while retaining IDs; a first zero does not create an empty IO. Invalid/duplicate/dangling historical links reject the entire batch without replacement or silent repair. The new suite contains 32 passing cases; existing arrangement tests now exercise real SQLite persistence rather than incomplete mocks.
  • Independent review identified repeatable-read visibility risks after waiting for locks. The generation, cancellation and monthly-contribution paths now use current locking reads; tenant-scoped weighing checks and clean-object refresh preserve caller pending fields. These paths passed 79 independently rerun bridge tests. Live concurrent MySQL behavior remains untested; isolated SQL-lock assertions and SQLite persistence are not a substitute for that validation.
  • Current-source frontend regression exposed rapid contract selection changes leaving an older contract's rows behind. The helper now filters rows with known contract identity against the latest selection, retaining unidentified legacy/manual rows. The original clearing assertions remain; the harness binds the real helper and fixtures include the contract IDs present in actual data. Three failing race cases became green.
  • Final root integration: 344 related backend tests passed, with both PyMySQL connection entry points blocked. Current-source Web/H5 tests: 143 passed; native miniprogram handler tests: 2 passed. Real edit/save/reopen/save and copy handlers are covered. Web production build passed in 45.97 seconds; existing component-name and bundle-size warnings remain. This is not a native device build or a repository-wide clean typecheck claim.
  • The required field-consistency command was attempted, but scripts/check_field_consistency.py is absent in the starting checkout. A broader metadata suite also depends on the pre-existing missing docs/sql/20261023_mobile_plan_stop_product_meta.sql; no unrelated file was restored. Focused changed-file whitespace checks passed.
  • Backend, frontend and miniprogram graphs were refreshed; root graph is refreshed after this record. All work stayed on codex/mobile-eight-pages-qa. No business database was accessed, historical data repaired, commit made or deployment performed. The user-approved legacy IO void/recreate lifecycle remains unchanged.

Fifth audit fixes approved by the user (2026-10-27)

The user explicitly authorized fixing the latest confirmed residuals. Work stays on the current branch; preserve unrelated changes, use isolated SQLite/mocks with business MySQL connections blocked, and do not commit/deploy or repair historical data.

  • CRM quote/contract products: reproduce accepted missing-ID, omitted-unit requests replacing a unique old line and changing its unit. Resolve anonymous product identity using only submitted discriminators after reserving explicit IDs; reuse unique active rows, reject ambiguity before writes, retain omitted fields and downstream protection. Preserve existing price-tier semantics.
  • Vehicle personnel: reproduce an anonymous same-name row selecting a different person via .first(), retiring the original vehicle link and creating a replacement. Require unambiguous identity, validate the entire collection before mutation, preserve link IDs and omitted personnel/link fields, and keep explicit insert/remove/clear behavior. Align the direct personnel upsert if it shares the same weakness.
  • Post-user bindings: reproduce the actual update route interpreting {} as userIds=[]. Omitted collection must preserve existing associations; explicit empty list clears; invalid null must not clear. Keep tenant/role security and ordinary differential binding behavior.
  • Verify red-to-green regressions, existing related backend and actual frontend handlers, independent review, changed-file whitespace checks and required field-consistency availability. Refresh backend and root graphs after implementation. Report actual verification and remaining environmental limits.

Fifth-audit implementation and verification

  • CRM quote and contract lines share a patch-aware anonymous-identity resolver. Matching merges only explicitly submitted fields into each candidate for comparison, preserving omitted unit/model/brand/package values. Explicit IDs remain reserved; ambiguous matches, repeated consumption and anonymous rows without product ID fail before writes. Contract downstream-reference protection and price-tier exact-key matching remain intact. The initial run exposed 40 behavioral failures plus one invalid fixture; after supplying its required PL fields, the new regression module passes 68 cases, including real update-schema and whole-document persistence paths.
  • Vehicle personnel no longer choose the first name/phone match. A single batch preparation resolves explicit IDs, rejects ambiguous active identities, merges consistent cross-role personnel fields, and validates final default-driver state before changing ORM objects. New people shared across driver/escort roles are created once. Existing person/link IDs and omitted phone/age/remark/default fields survive; explicit clearing is retained. The direct upsert uses the same resolver. The new module has 29 passing cases (initially 13 failures / 9 passes); 77 related cases passed independently.
  • Position-user PUT distinguishes omitted userIds from explicit [] after checking the position's tenant. Omission performs no DML or commit; null remains invalid by the existing schema. The new real-route SQLite suite has 15 cases; with the existing system relationship suite, 26 pass. Initially the omission regression failed while 14 other cases passed.
  • Three vehicle forms now send an explicitly cleared personnel-link remark as an empty string, so the new omission-preserving backend does not retain a remark the user removed. Their real submit handlers failed all 3 new sequence tests before the change and pass afterward; IDs and omitted read-only phone values are unchanged. Existing Web/H5/native ID paths were checked. No native product code change was needed for these backend fixes.
  • Final root integration: 692 related backend tests passed, with pymysql.connect and Connection.connect blocked globally; 37 Web/H5 handler tests and 2 native miniprogram tests passed. Web production build passed in 46.01 seconds. Independent review of the CRM, position and vehicle-personnel changes found no remaining blockers in the modified paths. Focused whitespace checks passed.
  • Limits: field-consistency command was attempted but scripts/check_field_consistency.py is absent. Expanded personnel-photo tests expose one existing fixture missing the current required trailerNo; the vehicle schema was not changed and that unrelated fixture was not rewritten. Existing dependency/build warnings remain. This does not claim a clean full-repository typecheck, device build, live MySQL concurrency test or historical-data repair.
  • Frontend/backend graphs were updated; root graph is refreshed after this record. Work remains on codex/mobile-eight-pages-qa, with existing worktree changes preserved. No business database connection, schema migration, commit or deployment occurred, and the user-approved IO void/recreate exception was unchanged.

Retrospective semantic audit after user scope correction (2026-10-27)

The earlier passing-test and completion notes are NOT acceptance of all behavioral changes. The user challenged treating omitted fields as erroneous clearing and requested scrutiny of this conversation's historical changes. New implementation was stopped. The audit compared the exact starting worktree, reconstructed from current HEAD plus /tmp/shanxia-child-save-starting-worktree.patch, with current files; unrelated starting edits were excluded. Reconstructed tracked source baselines are in /tmp/shanxia-review-baseline/. No business database or other branch was inspected.

Confirmed regressions introduced by this task — unresolved

  1. Certificate clearing: existing Web personnel/vehicle forms encode cleared certificate number, expiry and attachment fields as undefined/omitted. The added model_fields_set guard in pl_cert_service.save_owner_certs now retains the original values. Actual handler payload plus SQLite persistence reproduced the failure; the starting implementation cleared these values. Preserve ID reconciliation but restore the established full-row save semantics or explicitly design backward-compatible clearing; do not assume omission means PATCH in every endpoint.
  2. Plan stop clearing: actual buildLoadPayload/buildDeliveriesPayload omit cleared contact/notes fields. The new parent-field guard in replace_plan_stops retains old values. SQLite baseline/current comparisons confirm this change. Do not generalize all optional fields as unchanged without checking the caller contract.
  3. Role custom data scope: the existing UI sends dataScope=5 and omits scopeDetails after clearing all selections. The added scope_details is not None guard preserves old grants. Identical requests clear the relation in the starting implementation but leave it active now. Restore the established complete-scope-save behavior while retaining differential relation updates.
  4. Archive inventory compatibility: the starting implementation legitimately created multiple transactions for multiple internal stops sharing product/brand/direction. The new unique-posting-key check rejects such previously valid data with HTTP 409. An isolated test generated two transactions of quantities 2 and 3 using the real starting service, then reproduced current rejection. A compatibility/ledger design is needed; these rows must not simply be labelled corrupted history.

Scope expansions that need separate assessment

  • Four explicit migration utilities had their clear-before-import options disabled. A deliberate maintenance/migration replacement operation is not automatically an ordinary-save identity bug; blanket removal of these documented options went beyond the narrow fix.
  • BX workflow metadata edits (wf_name, and service-level remark) are now rejected when instances are pending, even with unchanged nodes. The baseline accepted these changes. Node topology/deletion guards and metadata edits require different treatment.
  • Contract reference guards now cover product-brand/model/unit/package identity changes as well as deletion; inventory corrections now preserve old create_time rather than reposting in the adjustment period. Their business semantics require review, not an assumption that stricter protection or stable IDs is always correct.
  • The three sixth-audit omission candidates (workPlans, approval settings and archive attachment lists) were reclassified as contract questions, not proven ordinary-save rebuild bugs. Existing complete forms explicitly submit their cleared lists. Their production behavior was not changed in that round.

Paused sixth-round implementation state

Only contract tier date identity normalization and its new test_crm_tier_date_identity.py had been implemented before the stop (16 targeted cases passed). test_duty_missing_identity_patch.py contains an unfinished reproduction (2 failing / 2 passing); no sixth-round duty production change was made. No approval-setting, archive-attachment or workPlans behavior change was made. These unfinished edits must not be represented as a fully verified delivery.

Evidence is recorded in /tmp/cert-clear-current-*, /tmp/pl-stop-clear-current-*, /tmp/pl-retro-inventory-compat.py, and /tmp/crm-bx-system-semantics-review.py. The root independently reran the certificate, stop-field, role-scope, workflow-metadata and old-inventory probes with MySQL connections blocked. No automatic rollback or further production fix was performed during this audit. Necessary child identity and repeated-contribution fixes should be preserved selectively; neither wholesale endorsement nor indiscriminate rollback is justified.