C02
The timing correction belongs in run_smoke: start the monotonic timer before collect_smoke_suite, finish after runner.run, and keep returning (TestResult, elapsed_seconds). This would include discovery/imports, recursive selection, runner construction and execution without changing membership. This is an assessment, not an implemented or tested result.
Current behavior
src/gzkit/smoke.py:81–131discovers the full unittest tier, imports test modules, walks nested suites and retains methods carrying the smoke attribute. Its timer starts only after collection and runner construction. Expensive imports and selection therefore cannot currently breach the budget.src/gzkit/commands/smoke_cmd.py:35–93first performs a separate static source scan. With no marked files, it returns advisory success unlesssmoke.requiredis true, when it returns 3. Otherwise, the returned elapsed value supplies both the printed summary and comparison. A test failure takes precedence (1); successful runs exceeding the budget return 3; equality passes. The wrapper raisesSystemExitfor nonzero results.- The runtime default is
SMOKE_BUDGET_SECONDSin code; Markdown is not dynamically read.--budgetremains a float override.SmokeConfig.requireddefaults false and controls empty-tier enforcement, not the budget on populated tiers. quality.run_smoke_tierinvokes the command as a subprocess; the quality command registers it as “Smoke tier.” The test-isolation chore also consumes its exit code.
Necessary coupled obligations and boundaries
- Define “elapsed” explicitly as collection through execution. Moving the timer inside
run_smokewould still exclude the preliminary static scan, config handling, process/CLI startup and final console reporting. If the intended contract is entire-command wall time, that requires a different boundary. Do not silently call this end-to-end CLI timing. - Preserve the return shape, runner verbosity/buffering, live discovery and marker filtering, budget override, strict
>comparison, failure precedence and adopter opt-in behavior. This is post-run enforcement, not a timeout that interrupts discovery or execution. - Document the expanded measured interval in the runner, CLI help, smoke manpage and canonical test rule; keep the distributed
src/gzkit/rules/tests.mdcopy aligned if the rule changes. Update breach guidance: dropping a marker does not remove that module’s discovery/import cost, so it cannot generally cure discovery-dominated breaches. The current message and help also claim the full tier has a larger budget, while the rule/manpage say no fixed ceiling; reconcile this touched explanatory surface. - Expect previously passing runs to breach without slower test execution. Do not compensate by silently raising the default or replacing discovery with a static roster. The check and chore consumers should inherit the corrected verdict; they need verification, not duplicate timers.
Meaningful verification proposed
- Use a deterministic fake monotonic clock advanced separately during collection/selection and execution. Assert total elapsed includes both and returns the original result. A test merely supplying two fixed clock values could pass even with the start call misplaced; phase-driven advancement must distinguish that mutation.
- Combine synthetic slow discovery and fast successful execution with the real gate path and assert policy breach plus the reported total. Cover below/equal/above budget, default/override and failure-plus-over-budget precedence. Keep output-contract assertions separate from behavior assertions.
- Retain empty-tier opt-in/out and shell-exit coverage. Verify nested marked selection and unmarked exclusion without running the entire repository repeatedly. Verify check wrapper propagation through a mocked subprocess boundary, then a separately authorized CLI integration check.
- Existing
tests/test_smoke_gate.pyexercises real repository runs with zero/default budgets and mocks a failure; it does not isolate discovery accounting. No tests or workflows were run here.
Uncertainty and existing edge
The static regex can find a decorator although runtime selection yields zero tests; there is no post-run zero-count guard. That is an existing separate correctness concern, not permission to expand this timing change. Discovery exception/import-error handling and cold-process headroom were not verified. No ownership or governance disposition is claimed.
Read inventory and limits
Eight shell calls total, including task read and this output write; two searches had path/glob errors. Full reads: /tmp/gzkit-current-inputs/C02.md; under /tmp/gzkit-current-snapshot/: src/gzkit/smoke.py, src/gzkit/commands/smoke_cmd.py, tests/test_smoke_gate.py, tests/cli/test_smoke_tier.py, docs/user/manpages/smoke.md, .gzkit/rules/tests.md, src/gzkit/rules/tests.md, .gzkit/chores/test-isolation-compliance/acceptance.json. Partial reads: src/gzkit/config.py, src/gzkit/cli/parser_maintenance.py, src/gzkit/quality.py, src/gzkit/commands/quality.py. Searches also exposed matching snippets across tests, docs/user and chores. Protocol limitation: the broad chores search incidentally exposed proof/audit snippets, including pair-review material; these were not opened or used as assessment evidence. This exposure prevents claiming a perfectly clean exclusion boundary. No source changes were made.