Skip to content

feat(plugin-contract): prove exact unload after a reload #36

Description

@ss-o

Feature description

The plugin-contract reload scenario (#34, #35) proves load, unload, load: the second load restores the first load's surface and its callback still works. It never unloads again after that second load, and the ordinary scenario never unloads a reloaded plugin. A plugin whose unload is exact the first time but leaks after a reload therefore passes every case.

Related Code

tests/_support/plugin-contract/scenario.zsh in #35 (head 8799b23), lines 68-83: the reload scenario ends after the effect check, and its comment leaves exact unload to ordinary.

Reproduced on 8799b23 with a fixture whose unload removes its precmd hook only once, keyed on a _zunit_* flag the observer excludes (the device reload-stale uses):

reload   noninteractive adv-second-unload: rc 0 (passes)
ordinary noninteractive adv-second-unload: rc 0 (passes)

The shipped fixture unloads exactly after a reload, so the check has a positive case today.

Additional Context

Found by the second independent review of #35 and left out of it by maintainer decision, so #35 merges as it stands with Refs #34. The organization testing standard asks that a separate clean-shell case load, unload and load again; it does not name the unload that follows, so this closes a gap the standard leaves open rather than one it requires.

Proposed change:

  • In the reload scenario, snapshot before the first load, then after the effect check unload again and assert plugin_restored against that first snapshot.
  • Add a negative fixture whose unload leaks only after a reload; it must fail reload and pass ordinary.
  • Reword the scenario comment that leaves exact unload to ordinary.

Acceptance criteria:

  • A fixture whose post-reload unload leaks fails the reload case, and the shipped fixture passes it.
  • ./zunit --tap tests passes on the native job.

Self-service

  • I'd be willing to address this myself.

Have you read the Contributing Guidelines?

  • I have read the Contributing Guidelines.

Are you familiar with the Contributor Covenant Code of Conduct?

  • I have read the Contributor Covenant Code of Conduct.

Activity

  1. added
    type:featureA request for new behavior or capability.
    on Sep 30, 2026
  2. ss-o commented on Sep 30, 2026

    @ss-o
    MemberAuthor

    Triage (Project 28 fields set from evidence):

    • Item Type Enhancement: extends the existing reload scenario's coverage; no current behavior is wrong in shipped code.
    • Impact Low: a plugin would need an unload that leaks only after a reload to slip through; no known plugin does, and the shipped fixture already unloads exactly.
    • Effort S: one extra snapshot, unload and assertion in scenario.zsh, plus one negative fixture, as the reproduction in the body shows.
    • Priority P2 - Medium: important for the contract's completeness but not urgent; it came out of test(plugin-contract): prove reload after unload (#34) #35's review and does not block other work.
    • Workstream Human delivery: ordinary maintainer-reviewed test work.

    Status stays Triage until the scope is agreed.

  3. moved this from Triage to Todo in Z-shell Deliveryon Oct 1, 2026
  4. ss-o commented on Oct 1, 2026

    @ss-o
    MemberAuthor

    Project 28 triage pass (2026-10-02): Status Triage -> Todo.

    • Premise confirmed on main at 6349b24: tests/_support/plugin-contract/scenario.zsh:68-83@6349b24 (main = merge of test(plugin-contract): prove reload after unload (#34) #35): the reload case ends after the effect check with no second unload and no pre-load snapshot. Probe: a fixture whose unload drops its precmd hook only once (flag under zunit*) passed both scenario.zsh reload noninteractive and scenario.zsh ordinary noninteractive (rc 0, rc 0); the shipped fixture also rc 0. A probe variant of the reload flow that snapshots before, unloads again after the effect check and asserts _zunit_assert_plugin_restored before after fails the leaky fixture (rc 1, 'hook:precmd') and passes the shipped fixture (rc 0), provided the scenario's own _contract_fixture_effect global is unset before the final snapshot.
    • Disposition: implement. Next action: implement against the acceptance criteria above; the work is ready to start.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:featureA request for new behavior or capability.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions