# E-021 — Two equivalent npm forms made a valid close incomplete

- Date: 2026-08-03
- Status: confirmed planning limitation; mitigated in schema-forge's contract.

## Objective hierarchy

- Main objective: detect deterministic drift with an early, traceable signal.
- Project objective: ETP-4708 in schema-forge.
- Round objective: make the preservation of fixed tests verifiable.

## Observed trajectory

To harden the contract, the final check `npm test`, with a five-minute timeout, was declared as evidence of the refactor's preservation. The suite passed in 38.6 seconds and criterion `AC-PRIMARY` was proven.

However, the planner also detected the package script as `npm run test`. Since it deduplicates by literal `argv` equality, it did not recognize the two commands as equivalent, added `package-test` as `discovered-not-configured`, and left it `skipped`. `round-end --mode final` returned `UNKNOWN` with classification `verification-incomplete`, even though the actual suite had passed.

## Correction and limits

schema-forge's contract was normalized to the canonical command `npm run test`; the subsequent close was complete. The current mitigation depends on the contract's author using the form the planner discovers.

This is not evidence that the suite is semantically sufficient, nor that PR #992 is green in remote CI. It also reveals a limitation of Objective Guard: the check model treats textually equivalent commands as distinct identities.

## Impact on the thesis

The signal was conservative: it did not produce a false `PASS`. That is preferable to approving incomplete coverage. But it adds avoidable friction and can erode trust if it forces users to learn the planner's syntactic conventions instead of reasoning about the check that actually ran.

## Follow-up

Add bounded semantic normalization for safe package-script aliases (`npm test` and `npm run test`), or emit a canonicalization recommendation before closing. Cover it with a regression test, and do not turn arbitrary commands into equivalents.
