Skip to content

feat(cli): opt-in exit contract for index_repository - #2092

Open
Blysspeak wants to merge 2 commits into
DeusData:mainfrom
Blysspeak:feat/graph-gate-contract
Open

feat(cli): opt-in exit contract for index_repository#2092
Blysspeak wants to merge 2 commits into
DeusData:mainfrom
Blysspeak:feat/graph-gate-contract

Conversation

@Blysspeak

@Blysspeak Blysspeak commented Sep 7, 2026

Copy link
Copy Markdown

Refs #2168

Opt-in exit contract for cli index_repository

A freshness gate cannot read a tool's account of itself, it reads the process
status. Today index_repository returns 0 for an index that parsed part of
the tree, and the same 1 whether the repository is missing or a pipeline fell
over inside one that exists. Callers cannot tell those apart.

Nothing changes unless CBM_GATE=1 is set. Without it the CLI exits
exactly as before. With it, grading happens in the CLI only; MCP responses are
untouched, so agents and scripts/soak-test.sh, which judge by JSON-RPC and
tool-level isError, see exactly what they saw before.

outcome today with CBM_GATE=1
indexed, clean 0 0
indexed, files parsed partially above threshold 0 2
indexed, a file did not parse at all 0 2
indexed, node count far below expectation (status: degraded) 0 2
pipeline failed inside a reachable repository 1 1
repo_path absent, unreadable, or not a directory 1 3

Thresholds, both optional, negative disables the check:

  • CBM_GATE_MAX_UNUSABLE, default 0, absolute count of unparsable files
  • CBM_GATE_MAX_PARTIAL_PCT, default 10, share of partially parsed files

The two defaults differ deliberately. A file that did not parse at all is a
defect and gets no tolerance. Partial parsing marks constructs a grammar does
not cover, a property of language support rather than of index quality: this
repository itself sits at 5.8% with a fully working graph. A gate its own
project cannot pass gets switched off, which protects nothing.

Additive fields

  • files_indexed and parse_partial_pct on the index response. The ratio had
    no denominator, and a gate that can only pass or fail cannot say how
    partial a parse was.
  • reason on failures, target_unavailable or pipeline_failed. The hint
    text read identically for both.

Verification

Full suite on this branch: 8001 passed, 1 failed, 7 skipped. The one failure is
daemon_ipc_posix_single_uid_userns_real_smoke_issue1830, which fails the same
way on a clean build of main at 055fbb7 on this machine (user-namespace
setup), so it is unrelated to this change.

13 tests in the cli suite pin the contract, including that an unset, empty
or 0 CBM_GATE leaves the historical status untouched.

End to end on this repository (clean git worktree of this branch, isolated
CBM_CACHE_DIR and CBM_RUNTIME_DIR), exit status read without a pipeline so
$? is the command's own:

gate unset:
  missing path                                   exit 1   (unchanged)
  this repository                                exit 0   (unchanged)
CBM_GATE=1:
  missing path                                   exit 3   reason target_unavailable
  this repository                                exit 0   files_indexed 1065, parse_partial_pct 5.8, under the default 10
CBM_GATE=1 CBM_GATE_MAX_PARTIAL_PCT=5:
  this repository                                exit 2

The same sequence against a binary built from main at 055fbb7 gives
1 / 0 / 1 / 0 / 0: today's status, unchanged by the variable.

@Blysspeak
Blysspeak requested a review from DeusData as a code owner September 7, 2026 16:05
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

Thanks for opening this — it has been seen, and it is queued.

This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence.

Current review status: working through a backlog. 0.9.1-rc.1 is out, so the release freeze that held reviews is over — but it left a large queue of open pull requests behind it, and we are reading through them oldest-first. The background is in discussion #1144.

What that means for this PR, concretely:

  • It will not be closed for inactivity. No stale bot touches pull requests here.
  • It may still sit a while before a human reads it. That is on us, not on you.
  • Older PRs are read first, so a recent one is not being skipped — it is behind a queue.

Things that will genuinely speed it up whenever review does happen:

  • Keep it rebased on main — the tree is moving quickly right now, and a conflicting branch cannot be reviewed as the diff you intended.
  • Get CI green, or say which failures you believe are pre-existing.
  • Keep the change to one claim. Bundled features and refactors get split before they get merged, which costs you a round trip.
  • Every commit needs a sign-off (git commit -s) — CI enforces DCO.

If this fixes a bug, a reproduction we can run is worth more than a description of the symptom.

Thanks for contributing, and sorry in advance for the wait.

@Blysspeak
Blysspeak force-pushed the feat/graph-gate-contract branch from d1abca2 to 1f08f82 Compare September 7, 2026 16:34
@DeusData DeusData added enhancement New feature or request ux/behavior Display bugs, docs, adoption UX editor/integration Editor compatibility and CLI integration priority/normal Standard review queue; useful PR with ordinary maintainer urgency. labels Sep 9, 2026
@DeusData

DeusData commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Thank you for the detailed CLI proposal and its tests. This spans exit-status semantics, environment defaults, output fields and index handling, so we need more time to review the compatibility and scope decisions before giving a direction. Please do not read the triage labels as approval of new defaults.

The review queue is currently full, so detailed feedback may take a little time. We are working through it carefully and appreciate the work you have put into supporting the project. Thank you for your patience.

@Blysspeak
Blysspeak force-pushed the feat/graph-gate-contract branch 2 times, most recently from b2bb18c to b317506 Compare September 10, 2026 14:49
A freshness gate cannot read a tool's account of itself — it reads the
process status. index_repository returned 0 for a partial index and the
same 1 for both a missing repository and a pipeline that fell over inside
an existing one, so no caller could tell those apart.

The CLI now grades its own outcome:

  0  indexed, quality at or above the thresholds
  1  hard failure inside a reachable repository (unchanged meaning)
  2  indexed but below a quality threshold
  3  repo_path absent, unreadable, or not a directory

The contract is opt-in: it applies only with CBM_GATE set to a non-empty
value other than "0". Without it the CLI exits exactly as before, so a
caller that never asked for grading never sees a new code. Grading
happens in the CLI only. MCP responses are untouched, so agents and the
soak test, which judge by JSON-RPC and tool-level isError, see exactly
what they saw before.

Thresholds are separate on purpose and overridable:
  CBM_GATE_MAX_UNUSABLE     default 0   a file that did not parse at all
  CBM_GATE_MAX_PARTIAL_PCT  default 10  share of partially parsed files

Partial parsing marks constructs a grammar does not cover — a property of
language support, not of index quality; this repository itself sits at
5.8%. A gate its own project cannot pass gets switched off.

Two additive fields carry what the grading needs:
  files_indexed, parse_partial_pct  the denominator the ratio needs and
      the share stated outright, so a gate can quote it in a refusal
  reason  on failures: target_unavailable vs pipeline_failed

Signed-off-by: Vladislav Rahmanov <rahmanov.official@yandex.ru>
The contract landed measured but unpinned: six outcomes were checked by
hand against the built binary and written into the pull request, and
nothing in the suite would notice if a code moved. A verification that
does not run again is a claim, not a test.

Twelve cases over cbm_cli_index_exit_status, which grades a result
envelope into a process exit code:

  clean run stays 0; an unusable file and a partial share above the
  ceiling both grade 2; "degraded" grades 2 on the status alone; an
  absent target grades 3 while a pipeline failure keeps 1 — the pair
  that shared code 1 before and gave the whole contract its reason.

Three of them exist to fail if the grader stops working rather than to
pass when it does:

  - the ceiling itself is exercised from both sides, 10 of 100 passing
    and 11 failing, because a test that only checks obvious excess stays
    green with the check switched off entirely;
  - the threshold overrides carry a positive control at the defaults, so
    "passed after raising the ceiling" cannot be confused with "no check
    ran";
  - eight unreadable threshold values are pinned to fall back on the
    documented default, since a typo that silently disables a gate is the
    failure the strict parse was written to prevent.

Silence is pinned too: a null, empty, unreadable, or content-less
envelope preserves the base status in both directions. Inventing a
quality verdict out of an unparsable payload would fail runs for the
crime of an unexpected response shape.

Envelopes are built with yyjson rather than hand-escaped, so the
payload's quoting is the transport's and not the test's own.

Signed-off-by: Vladislav Rahmanov <rahmanov.official@yandex.ru>
@Blysspeak
Blysspeak force-pushed the feat/graph-gate-contract branch from b317506 to b037b48 Compare September 10, 2026 14:50
@Blysspeak Blysspeak changed the title feat(cli): grade index_repository outcomes with distinct exit codes feat(cli): opt-in exit contract for index_repository Sep 10, 2026
@Blysspeak

Copy link
Copy Markdown
Author

Reworked after your note on defaults, and narrowed to one claim per the contributing guide.

The contract is now opt-in: nothing changes unless CBM_GATE=1 is set, so no existing caller sees a new code. graph_generation, seed_symbols_list, absolute_path and .cbmignore are out of this PR; if any of them is wanted I will open an issue for it separately.

Rebased on main, clang-format fixed, tracking issue #2168 with measurements on a clean main build and on this branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

editor/integration Editor compatibility and CLI integration enhancement New feature or request priority/normal Standard review queue; useful PR with ordinary maintainer urgency. ux/behavior Display bugs, docs, adoption UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants