Projects › Lists › ProjectTasks › View item

ContentType: ContentType.ProjectTask   Item: gov-8a

Test impact: the four remaining proposal park sites become data
2026-09-30T15:26:28.7453347+00:00
claude-code
GOV.8a
GOV
Test impact: the four remaining proposal park sites become data
(empty)
(empty)
1
Completed

Role: test impact scout (read-only). The change: AutoGenesisToolInvoker, BuildDivisionToolInvoker, ExtractSkillToolInvoker and SelfReviewProposalRouter stop naming Engineering as the site their ApprovalRequest parks on; each reads a declared task list instead (Workflow TaskListSite/TaskListTitle already exists, commit 3cb8c96). Deliver in TaskOutcome: every test that asserts Department=Engineering or the Engineering/ApprovalRequests path for these four, as file:line plus the exact assertion, and which of the four has a part (Tool, Workflow) in reach to carry the attribute.

Outcome (spice-impact-scout, 2026-09-30): GOV.8a test impact (read-only). Scope: AutoGenesisToolInvoker, BuildDivisionToolInvoker, ExtractSkillToolInvoker, SelfReviewProposalRouter stop naming Engineering as the park site.

HARD BREAK (asserts the literal today):

  • SelfReviewProposalRouterTests.cs:71 Assert.Equal("Engineering", (string?)op.Attribute("Department")) in Self_review_completion_synthesizes_addlistitem_against_engineering_approvals (line 56). Conditional: RequestFor() (line 156) builds PhaseRequest positionally with 5 args so WorkflowId is null; if the router follows the FinalDeltaApplyListener pattern (wf?.TaskListSite ?? "Engineering") this line stays green and proves nothing about the new path -> SAFE-BUT-VACUOUS if default stays Engineering, WILL-BREAK if the default flips to Compliance (GOV.8 parent evidence floats that). Fix: add a test passing WorkflowId="Workflow.SelfReview" + a StubParts Workflow carrying TaskListSite, or the change ships untested.
  • BuildDivisionToolInvokerTests.cs:134 storage.Enumerate("Engineering", "ApprovalRequests") in Parked_division_round_trips_to_the_served_ApprovalRequests_list (line 119). Same conditional logic - WILL-BREAK only if BuildDivisionToolInvoker's resolved site stops defaulting to Engineering.

COMPILE-BREAK RISK (positional construction, not assertions):

  • SelfReviewProposalRouter ctor has no IPartLibrary param; tests construct it new SelfReviewProposalRouter(applier, NullLogger...) at lines 35, 47, 59. Adding IPartLibrary to resolve Workflow.SelfReview breaks all three unless trailing-optional (IPartLibrary? parts = null), the AutoGenesis dmn/settings precedent already in that class.
  • ExtractSkillToolInvoker.BuildApprovalDelta(parkKey, skillId, sourcePipeline, addSkillDelta) called positionally (4 args) at SkillLibraryExtractSkillTests.cs:297. Adding a site param breaks this call unless trailing-defaulted.
  • BuildDivisionToolInvoker.BuildParkDelta(parkKey, title, subject, reason, inner, issuer) (6-arg static) called from RequestSiteToolInvoker.cs:54 (non-test, but breaks the test build if the signature changes without a default).
  • RequestSiteToolInvoker.cs:75-76 embeds BuildDivisionToolInvoker.Site directly in an operator-facing message string ("parked at /sites//Lists/..."). If Site stops being a readable const, this fails to compile; if it changes value, the message text must track it. Checked RequestSiteTests.cs: no Engineering/Site assertion there - SAFE, but the source dependency is real.

SAFE (confirmed, would mislead if 'fixed'):

  • AutoGenesisToolInvokerTests.cs:156-159 comment says 'AddListItem into Engineering/ApprovalRequests' but the actual assertion only checks Attribute("List")=="ApprovalRequests", never Department - SAFE, comment is stale.
  • AutoGenesisToolInvokerTests StubEnumerator.Enumerate(siteName, listName) (lines 82-87) ignores siteName entirely, filtering only on listName. So Open_row_with_a_reject_verdict_is_not_overwritten and Owned_status_row_is_not_overwritten (lines 246, 258) pass regardless of what Site resolves to - SAFE BUT BLIND to a real hazard: AutoGenesisToolInvoker.Site is triple-duty (park Department at BuildParkDelta:413, the R8 park-guard READ site at ReadExistingRow's enumerator.Enumerate(Site,...):242 and LoadLinkedVerdicts(enumerator, Site, ...):253, and ResolveContext(Department: Site) feeding the IdleCap/WorkCron settings at 300/305). If only the write path follows the new site while reads stay on Site's old resolution (or vice versa), R8 would read Engineering while writing Compliance and re-park over a human-owned row - the stubbed tests cannot catch that divergence. Recommend the resolved site feed both the read (242/253) and write (413) call sites identically, and leave the settings ResolveContext keyed on whatever Scope.AutoGenesis already uses (don't move it incidentally).
  • SkillLibraryExtractSkillTests.cs:323-327 Assert.Equal("Engineering", dept) in ResolveDepartment_prefers_the_explicit_arg - this is the Skill-binding target (AddSkillBinding/department= arg), unrelated to the ApprovalRequest park site. SAFE, do not touch.
  • SelfReviewProposalRouterTests.cs:107-121 Live_manifest_declares_engineering_approvalrequests_list pins that EngineeringPortal/ApprovalRequests exists in the manifest - stays true (the site isn't being deleted) but becomes the wrong pin once SelfReview's park moves; add a sibling assertion for whatever site Workflow.SelfReview's TaskListSite ends up naming.
  • SkillLibraryExtractSkillTests.cs BuildApprovalDelta_parks_an_open_ApprovalRequest_carrying_the_AddSkill_delta (lines 290-314) never asserts the Department attribute at all despite ExtractSkillToolInvoker.cs:337 hardcoding Department="Engineering" - SAFE, no test regression from changing that literal, but also no test coverage of the new value; consider adding one.

WHICH OF THE FOUR HAS A PART IN REACH (verified against SAF-Parts.xsd:1314-1317 - TaskListSite/TaskListTitle are declared ONLY on WorkflowType, not ToolType):

  • SelfReviewProposalRouter: YES, cleanly in reach. It already implements IPhaseCompletionListener.OnPhaseCompletedAsync(PhaseResult, PhaseRequest, ct) - the exact signature FinalDeltaApplyListener uses, and PhaseRequest already carries WorkflowId (IPhaseOrchestrator.cs:44, added for GOV.8). Workflow.SelfReview exists (Parts.xml:3280, single Phase.SelfReview step). Needs: inject IPartLibrary (trailing-optional ctor param), resolve via request.WorkflowId like FinalDeltaApplyListener.cs:73-76, and Workflow.SelfReview would need a TaskListSite/TaskListTitle attribute added if the desk should differ from the Engineering fallback. Lowest-risk, most reusable of the four - literally the same pattern GOV.8 just proved.
  • BuildDivisionToolInvoker (Tool.BuildDivision): adjacent, not owned. Workflow.GenesisBuildDivision already declares TaskListSite="Compliance" TaskListTitle="ApprovalRequests" (Parts.xml:2774) but Tool.BuildDivision is the deterministic direct-chat path explicitly separate from that 3-phase workflow (see the invoker's own doc comment) - it is never invoked as a step of Workflow.GenesisBuildDivision and receives no WorkflowId. Wiring it to that Workflow's attribute would require a new, hand-picked lookup (_parts.Of<Workflow>() by a hardcoded Workflow.GenesisBuildDivision id), which is a judgment call, not a mechanical reuse.
  • AutoGenesisToolInvoker (Tool.AutoGenesis): no Workflow in reach (invoked directly from a Schedule/CrewWork run, not a Workflow step). It already has the zero-new-seam alternative: ISettingsResolver + Scope.AutoGenesis are already injected and used for SettingIdleBornCap/SettingWorkCron (lines 63-64, 299-305) - a third SettingParkSite/SettingParkList pair is the path of least resistance, not a Workflow attribute.
  • ExtractSkillToolInvoker (Tool.ExtractSkill): nothing in reach. No Workflow, no ISettingsResolver currently injected, and Tool (the part kind it is) carries no TaskListSite/TaskListTitle attribute in the XSD. Would need either a new ISettingsResolver injection (mirroring AutoGenesis) or an XSD-level addition of TaskListSite/TaskListTitle to ToolType - the only one of the four requiring an XSD change if a per-tool-declared site is wanted.
spice-impact-scout
GOV.8
100
(empty)
(empty)
(empty)

Attachments

No attachments.

+ Attach a file
Status:Completed
✓ This item has reached its final state.