Skip to content

docs(test): version-gate device expectations, and prove them on long-term (#297) - #301

Merged
mobileskyfi merged 1 commit into
mainfrom
docs-297-version-gating-convention
Aug 15, 2026
Merged

docs(test): version-gate device expectations, and prove them on long-term (#297)#301
mobileskyfi merged 1 commit into
mainfrom
docs-297-version-gating-convention

Conversation

@mobileskyfi

@mobileskyfi mobileskyfi commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Fixes #297.

Records the decision #297 was waiting on and writes it where a cold agent reads it before writing an integration test — its second acceptance criterion — rather than leaving it in an issue.

Adopted: convention (option 1) + a local, scoped long-term run in the done definition. Not a pre-merge CI leg.

Why not the CI gate

The cost estimate in the issue measures the wrong run. A full leg really is ~18 minutes — measured on the failing run: stable 17m, long-term 18m, testing 18m, development 16m. But what finds this drift is the touched file against the oldest device, and that is not expensive:

Scope Wall time
one file (mcp.test.ts) on long-term 22s
two files (mcp + execute) 73s
two files (explain-values + explain-string-escape) 120s
a full CI leg ~18m

So this doesn't need to be a gate at all. Every version-drift instance in #297 would have been caught by a ~20-second local run before the PR was opened.

I ran the documented command rather than documenting an unrun recipe — it resolves long-term → 7.21.5 and passes:

CENTRS_CHR_CHANNEL=long-term CENTRS_RUN_FAST_INTEGRATION=1 \
  bun test test/integration/<touched>.test.ts

Three surfaces, one canonical statement plus pointers

  • test/AGENTS.md — the rule. test/CLAUDE.md is a symlink to it, so Claude and Copilot both pick it up from one edit. Includes a table mapping each existing contract to when it fits, and the two standing traps: gate on the running version, never the channel name (channels move); and never relax an assertion to make a version pass — explain-values integration tests hard-code ≥7.23 device behaviour (blocks the long-term gate) #296 kept a byte-exact offset on every version, just not the same byte.
  • .github/instructions/done-definition.instructions.md — the long-term run as step 3 of the existing procedure, pointing at the rule rather than restating it.
  • test/integration/chr.ts — a section header over the contracts, naming the two shapes and why they are not interchangeable: an accepted set when several answers are all correct, a version boundary when the behaviour genuinely changed and the test must still assert exactly on each side.

Scope, stated rather than implied

This prevents version drift. A harness that mishandles normal teardown — #300's unhandled socket error when the relay peer exits — is a different failure that only shows up by running the thing, and would not have been caught by any of this. Saying so in the doc keeps the next reader from treating it as flake prevention too.

One premise in the issue is already stale

"Used exactly once" no longer holds: routerOsAtLeast() now has three integration call sites (transfer.test.ts:242, explain-values.test.ts:112 and :560), VALIDATION_REJECT_CODES has five assertion sites across four files, and PARSE_REJECTED / PARSE_REJECTED_HINT were added in the same shape for a wording split where the obvious /error/ matcher silently accepted nothing.

The mechanism gets reached for once someone knows it exists. Discovery was the gap, which is why the fix is three pointers and no new machinery.

bun run lint:ci, bun run test (2854) and bun run build all clean.

Summary by CodeRabbit

  • Documentation

    • Clarified integration-testing requirements for stable and long-term RouterOS channels.
    • Added guidance for documenting and handling version-dependent device behavior.
    • Improved instructions for distinguishing version changes from teardown-related test failures.
  • Tests

    • Expanded validation expectations to include long-term channel coverage.
    • Standardized version-aware assertions and shared integration-test contracts for more reliable compatibility checks.

…term (#297)

Records the decision #297 was waiting on, and writes it where a cold agent
reads it before writing an integration test rather than only in the issue.

Adopted: convention (option 1) plus a LOCAL, scoped long-term run in the done
definition. Not a pre-merge CI leg — the cost estimate in the issue measures
the wrong run. A full leg is ~18 minutes (measured: stable 17m, long-term 18m,
testing 18m, development 16m), but what finds this drift is the TOUCHED file
against the OLDEST device, and that is ~22s for one file, 73-120s for two:

  CENTRS_CHR_CHANNEL=long-term CENTRS_RUN_FAST_INTEGRATION=1 \
    bun test test/integration/<touched>.test.ts

Verified that command resolves long-term (-> 7.21.5) and passes, rather than
documenting an unrun recipe. Every version-drift instance in #297 would have
been caught by it before the PR was opened.

Three surfaces, one canonical statement plus pointers:

- test/AGENTS.md (test/CLAUDE.md symlinks to it, so both harnesses get it) —
  the rule, with a table mapping each existing contract to when it fits, and
  the two standing traps: gate on the running VERSION not the channel name,
  and never relax an assertion to make a version pass.
- .github/instructions/done-definition.instructions.md — the long-term run as
  step 3 of the existing procedure, pointing at the rule.
- test/integration/chr.ts — a section header over the contracts naming the two
  shapes (accepted set vs version boundary) and why they are not
  interchangeable, so the surface is discoverable from the code.

Scope stated explicitly: this prevents VERSION DRIFT. A harness that
mishandles normal teardown (#300's unhandled socket error when the relay peer
exits) is a different failure that only shows up by running the thing, and
saying so keeps the next reader from reading this as flake prevention too.

The issue's "used exactly once" premise is already stale: routerOsAtLeast now
has three integration call sites and VALIDATION_REJECT_CODES five, with
PARSE_REJECTED/PARSE_REJECTED_HINT added in the same shape. The mechanism gets
reached for once someone knows it exists — discovery was the gap.

Fixes #297

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 15, 2026 01:08
@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0e2b002e-bcb6-4008-b8c4-25dc1186f9e9

📥 Commits

Reviewing files that changed from the base of the PR and between 50d6bd7 and a85abdf.

📒 Files selected for processing (3)
  • .github/instructions/done-definition.instructions.md
  • test/AGENTS.md
  • test/integration/chr.ts
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (5)
test/**/AGENTS.md

📄 CodeRabbit inference engine (test/CLAUDE.md)

Document agent configurations and behavior expectations in AGENTS.md

Files:

  • test/AGENTS.md
**/AGENTS.md

📄 CodeRabbit inference engine (AGENTS.md)

Use directory-level AGENTS.md files only for local constraints.

Files:

  • test/AGENTS.md
{docs/**,.github/instructions/**,.github/**/*.yml,.github/**/*.yaml,**/*.{md,txt,dict}}

📄 CodeRabbit inference engine (AGENTS.md)

Run bun run lint:ci when changing documentation, instructions, security configuration, spelling dictionaries, or workflow files.

Files:

  • test/AGENTS.md
  • .github/instructions/done-definition.instructions.md
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Transport or RouterOS-touching code is not done until bun run test:integration passes.
Do not silently fall back to another protocol when the caller pinned --via.
Do not make generated output the hand-edited source of truth.
Do not disable validation to make a test pass; validation is part of the product.

Files:

  • test/integration/chr.ts
.github/instructions/*.instructions.md

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Store Copilot's path-specific durable instructions in .github/instructions/*.instructions.md files using applyTo front matter

When an issue requires an instruction file, read that file directly; otherwise consult the instruction map to identify applicable path-scoped rules.

Files:

  • .github/instructions/done-definition.instructions.md
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: tikoci/centrs PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2026-06-15T16:06:55.935Z
Learning: Applies to test/**/AGENTS.md : Document agent configurations and behavior expectations in AGENTS.md
Learnt from: CR
Repo: tikoci/centrs

Timestamp: 2026-08-15T01:50:26.089Z
Learning: Collect coverage for trend visibility, not as a percentage gate.
Learnt from: CR
Repo: tikoci/centrs

Timestamp: 2026-08-15T01:50:26.089Z
Learning: Run the file you touched against `long-term` before calling it done.
🔇 Additional comments (3)
.github/instructions/done-definition.instructions.md (1)

28-41: LGTM!

test/AGENTS.md (1)

8-50: LGTM!

test/integration/chr.ts (1)

110-131: LGTM!


📝 Walkthrough

Walkthrough

The PR updates integration-test guidance. Device-output tests must run against the long-term CHR channel. RouterOS version differences must use shared contracts and reported-version checks.

Changes

RouterOS integration guidance

Layer / File(s) Summary
Long-term CHR validation workflow
.github/instructions/done-definition.instructions.md
The done-definition workflow adds a long-term CHR run for integration tests that assert device output and renumbers the result-recording step.
Version-dependent test contracts
test/AGENTS.md, test/integration/chr.ts
Testing guidance documents shared RouterOS behavior contracts, version-based gating, exact assertions, and the distinction between version drift and teardown failures.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to a85ab

This localized documentation change clarifies version-gated device expectations and the long-term test procedure; no actionable merge-blocking risk remains after normal checks and review.

Possibly related issues

  • Issue 283 — Both changes define shared handling for RouterOS version-dependent integration-test expectations.

Possibly related PRs

  • tikoci/centrs#55 — Adds related CHR integration testing and stable-channel workflow coverage.
  • tikoci/centrs#180 — Introduces the shared RouterOS version comparator referenced by this guidance.
  • tikoci/centrs#298 — Adds concrete version-gated contracts and assertions in test/integration/chr.ts.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the documentation change and the long-term channel validation required by the pull request.
Description check ✅ Passed The description provides the issue link, change approach, validation results, and RouterOS assumptions, although it does not follow the template headings exactly.
Linked Issues check ✅ Passed The changes record the decision, document it for agents, name the existing contracts, and add the scoped long-term run required by issue #297.
Out of Scope Changes check ✅ Passed All changes support issue #297 by documenting version-drift prevention and the scoped long-term test procedure.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs-297-version-gating-convention

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses #297 by documenting (in the places a “cold” contributor/agent will read first) how to express RouterOS version-dependent integration expectations, and by adding a lightweight local verification step to catch long-term-only behavior splits before a PR is opened.

Changes:

  • Adds a “device-behaviour contracts” header in test/integration/chr.ts to make version-split expectation patterns discoverable at the declaration site.
  • Documents the “declare the split in chr.ts” convention and provides guidance on choosing the right contract in test/AGENTS.md.
  • Updates the done-definition workflow to include a scoped long-term run of the touched integration test file when assertions read device output.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
test/integration/chr.ts Adds a prominent section header framing where/how RouterOS version-split contracts should be declared.
test/AGENTS.md Documents conventions for version-dependent assertions and when to run a local long-term CHR check.
.github/instructions/done-definition.instructions.md Extends the “done definition” checklist with a scoped long-term run step for device-output assertions.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@mobileskyfi

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@mobileskyfi
mobileskyfi merged commit 17671d4 into main Aug 15, 2026
12 checks passed
@mobileskyfi
mobileskyfi deleted the docs-297-version-gating-convention branch August 15, 2026 03:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Device-grounded integration assertions keep landing pinned to stable, and long-term finds them days later

2 participants