test(codascon): close all open test gaps (§17 multi-hook, §18 strategy lifetime, §_CSS3 callable proof)#64
Conversation
…(§17) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Reviewed. §17 adds two it blocks. First: food === 'morning' requires groomResult.groomed (GroomCommand invoked) AND logEntry.action (LogCommand invoked) — neither hook can be dropped without breaking the assertion. Second: running with different time values shows hooks are called fresh on each run(), not memoised. CommandHooks<[LogCommand, GroomCommand]> structural requirement (log + groom properties) is enforced at compile time by tsc. No existing tests touched. 44/44 pass. |
…e (§18) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…CSS3) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Reviewed. Verified: §17 both-hooks invoked and result depends on both (groomResult.groomed selects branch, logEntry.action provides value); §18 cached vs fresh strategy instances behave as expected; _CSS1/_CSS2 correctly use the base class form to work around the circular-inference limitation (documented); _CSS3 callable proof compiles; all 46 tests pass and build clean. |
…ngling reference @internal + stripInternal strips the type declaration but leaves the reference in run()'s this constraint, breaking consumer type-checks. Reverted to non-exported. _CSS1/_CSS2 removed; _CSS3 (callable proof) + §14 (@ts-expect-error) cover the gap. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Addresses all open gaps in the codascon test suite identified in the test analysis.
Summary
§17 — Multi-hook H tuple at runtime: adds two
itblocks forRichFeedCommand extends Command<..., [LogCommand, GroomCommand]>. Both hooks are invoked insideexecute; the result depends on both hook return values, so the assertion only passes when both hooks fire. A seconditverifies hooks are re-invoked (not cached) on eachrun()call.§18 — Strategy statefulness (cached vs fresh): adds two
itblocks contrastingCachingCommand(holds aCountingStrategyinstance as a field — state accumulates acrossrun()calls) vsFreshCommand(creates a newCountingStrategyon everyresolveDogcall — state resets). Confirms the framework is neutral about strategy lifetime._CSS3—CommandSubjectStrategiescallable proof: adds a callable proof toconstraints.test.ts.cmd.run(dog, { time: "x" })compiling proves that a correctly implementedFeedCommandsatisfies its ownthis & CommandSubjectStrategies<...>constraint. If any visit method were missing or had the wrong signature, tsc would reject the call site.Limitation (documented in
typescript-gotchas.md):CommandSubjectStrategiesis an internal (non-exported) type used as thethisconstraint onrun(). It cannot be exported with@internal—stripInternal: truewould strip the declaration while leaving the reference inrun()'s signature, producing a dangling name in the published.d.ts. Shape assertions (_CSS1/_CSS2) were attempted and reverted for this reason._CSS3+ the@ts-expect-errorblocks in §14 together close the gap.Test plan
pnpm --filter codascon test— 46 tests pass (36 runtime + 10 compile-time)pnpm --filter codascon build— tsc succeeds;CommandSubjectStrategiesstays as private declaration in.d.ts, no dangling reference🤖 Generated with Claude Code