Repository navigation
test(mcpverbscheck): pin the exact advertised MCP verb roster — constant-count swap tripwire - #1
Merged
Merged
Conversation
…stant-count swap must not slip a verb in
Adds (6b)/(6c) to the L4 section. L4_COUNT==31 fails closed on a verb ADDED
and the per-name arms pin the L4/field-notes verbs individually, but a rename
or swap that keeps the count at 31 and touches a verb no arm names (analyze,
grep, the edit trio, ...) passes every existing arm — CONTRIBUTING §2 shape 7
('true but narrower'). (6b) pins the full sorted advertised roster so ANY
add/remove/rename reddens until a human signs for it; (6c) is the mutation
control proving (6b) can see a new verb, plus a named tripwire asserting no
shell/exec-shaped verb is advertised (--run-trace stays CLI-only).
Context: security-audit follow-up. Both audit findings closed clean — M1
(report XSS) not-a-bug, verified end-to-end: jsonesc::escapeHtml \uXXXX-escapes
<>& at emission and all 8 innerHTML sinks escape repo-derived values or
interpolate integers/constexpr vocab. L1 (--run-trace reachable from MCP) was
never a vuln: no such verb exists. This arm is invariant-hardening so that
stays true, not a vuln fix.
Verified on a real build: planted lego->run_trace in kMcpVerbTable + the
tools/list stanza (constant-count swap) — L4_COUNT==31 stayed green, (6b)
reddened with the diff, (6c) tripwire reddened; reverted, gate ALL PASS.
New arm in an existing gate file — no regression.sh or gate-count ride-along.
pt-act
pushed a commit
that referenced
this pull request
Sep 21, 2026
…ffer lane/expand-ambiguous-bodies added the --expand ride-along note= attribute, formatted into main.cpp's char noteBuf[220] (runDefaultMap). fixedbufsweep.sh re-derives its whole fixed-buffer population from source every run (CLAUDE.md non-negotiable #1: a plausible-looking classification is not a checked one), so the new call site failed as UNCLASSIFIED, and the pinned S6 enumeration (calls/mentions/sites/rows) had drifted by one each (CI run 35418635836). Added a TABLE row: noteBuf's ONE interpoland is mapTopK, an int (11 digits worst case) — 121 B of fixed literal + 132 B total against 219 usable + NUL, 87 B of margin, no string interpolation and nothing user-supplied, so "safe" by the same all-numeric reasoning as this file's fileOpen/bundleOpen rows. Re-derived EXPECTED (225->226 calls/sites, 333->334 mentions, 98->99 rows) from the gate's own INFO line rather than by arithmetic, per the file's own header rule, and appended a dated round entry to the pin's history comment. caught-by: CI (run 35418635836, fixedbufsweep.sh, S1/S6) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
pt-act
pushed a commit
that referenced
this pull request
Sep 21, 2026
…e attribute, not the word The §F5 sweep over this lane's changed files caught a second consequence of the merge-scout/scan-skills legend fix (#1): --scan-skills' new --legend=full comment spells the word "skipped=N" in PROSE (no quote) to define the attribute, per the house name= convention legendcoveragecheck's definitional predicate requires. §B13.3's "nothing was skipped, so the attribute must be absent" check grepped the WHOLE output for the bare substring `skipped=`, which the prose now matches on every run regardless of whether the real attribute (` skipped="{}"`, src/skillscan.h) is present. Matched as `skipped="` (the attribute's exact spelling, quote included) instead — real leaked attribute still fails the arm, the legend's own prose defining what the attribute WOULD mean no longer does. Red before: "(§B13.3) skipped= leaked on a directory where nothing was skipped" / "the single-file artifact grew a skipped= attribute" on both --legend=full arms, unconditionally (the legend comment is present on every run in that posture). Green after: ALL PASS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
pt-act
pushed a commit
that referenced
this pull request
Sep 21, 2026
…egend edits UPDATE_GOLDEN=1 after the §F5 sweep caught it: --help=all's bytes moved (the --readability UNVALIDATED note, redhat-et#8) and --pack-task's bytes moved (the new unconditional bodyless= clause in kPackTaskBundleLegendBody, #1 — it rides in every bundle by design, so it moves every --pack-task hash). Both are real, intended content changes, not a printf-family conversion defect; re-pinned with UPDATE_GOLDEN_EXPECT="help_all pack_task" so the gate would have refused a third, unexplained mover. test/printffmtparitycheck.sh: ALL PASS — printf-family byte parity holds over all 42 verbs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
pt-act
pushed a commit
that referenced
this pull request
Sep 28, 2026
…ixtures, at most 2
The pre-registered second round of the named-identifier anchor, on top of round 1:
(a) call syntax on a plain word is not identifier evidence when the task carries
pasted code (a fence, an indented line, or stack-trace lines by the shipped
trace classifier);
(b) a definition in the test/fixture rank tier, or test-scoped, is not a target
unless the task names its file;
(c) at most 2 identifier-resolved symbols per task, the rest disclosed by the
existing mention_syms_capped= / mention_syms_total= (condition now total > kept,
unchanged for Scope.name mentions);
(d) every directly named symbol takes the below-#1 slot again, so the anchor never
displaces #1.
mentioncheck arm (vii) rewritten: named symbols enter the served head below an
unchanged #1; controls for a fenced and an indented paste, a fixture-only target
and its named-file exception, and the per-task cap. Red on the base binary.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pt-act
pushed a commit
that referenced
this pull request
Sep 28, 2026
… size_t on every miss (G1 integer abort) Both CI asan jobs failed editcheckcheck arm (g) with "no <edit-check element (rc=0, stdout bytes=0)": the rc was sed's, not ripwire's. ripwire aborted (134) under -fsanitize=integer at resolve.h JsonNode::get: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'std::size_t' #0 JsonNode::get #1 packageJsonWorkspaceGlobs #2 ImportResolver::collectWorkspaceMembers ... redhat-et#11 buildGraph (graph.h:2703) Cause: `for( std::size_t i = keys.size(); i-- > 0; )` decrements 0 on every key MISS. The loop dates from redhat-et#220 part 1 (train 20) but was dormant on this repo; lane/ts-alias-resolve-220 (merged 4ca7133) added collectWorkspaceMembers, which asks this repo's package.json for a `workspaces` key it does not have, so every graph build aborts under G1. The same lane's workspace-glob matcher (9627c27) has the same idiom in both of its DP loops. Not a gate-pin issue: src/graph.h:find resolves on the plain build (defs=1). Fix: the house cursor shape (mention.h, namesplit.h, ingest_names.h) at all three loops; no behaviour change. Red-first arm: test/depsprecisecheck.sh already drives every tsconfig/package.json/workspace reader; under the llvm@22 asan tree it went 19 PASS / 73 FAIL (72 aborts at resolve.h:1966) before, ALL PASS after. It was never in CI's asan job, so it is added there, next to editcheckcheck. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pt-act
pushed a commit
that referenced
this pull request
Oct 12, 2026
… pins - Exact-row gate greps now assert the row's sites_at= value as well (affected, cpptmplscope, decline, kotlin, rootspelling, callers #1/#2); safe-delete arms move from sites_l= to sites_at= with a twin that sites_l= is gone. - Re-pins, each with a twin holding the old number minus the one new sentence: compactlegendcheck callers/v1 330->450, safe-delete/v1 820->840, ten-verb loop 7800->7900, the callers A-PIN re-anchored; graphlegendbudgetcheck callers 3429->3769; donelegendcheck's sd_uses twin cuts the new sentence. printf parity manifest re-pinned (callers, callers_json, callers_limit, safe_delete, help_all only). - Full-legend clause shortened; JSON-safety of the MCP note is a static_assert; graphlegend.h clang-formatted. - README captures show sites_at=; LIMITS.md and the README cap count regenerated (241); CHANGELOG entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
joyful-ii-V-I
pushed a commit
that referenced
this pull request
Oct 21, 2026
…rget; rule-4 gate twins - kForRunawayGuardBytes = 30,000 B by the frozen rule: max(4 x 7,500, 2 x the largest complete default payload on the round-2 --for argv (12,519 B)); zero hits on the round-4 and capsweep argv (max 13,005 B). - The default answer narrows <lego>/<compose> to the rows at its target cut (sigsRowsAtTarget), so the rows kept past the target do not turn a served lego section into a stub (the section invariant). - An exhausted soft target's hops marker clears the hop-only readings (via=, owner qword), so the owner plan adds nothing there (ownerhopcheck B2). - MCP from_trace names its budget_tokens on the root and reads it as a soft target, like the CLI twin; the compact from-trace reading says "soft". - Rule-4 replacements (no gate erosion; each replaced arm green on head and red on base where it asserts the new behaviour, twins green on both): estchargecheck, ceilingverdictcheck (FORGE kept), formaxtokenscheck (E), w3fixbudgetcheck, forsigspancheck (T), tracecheck (T3), mcpforparitycheck (5), fordisclosurecheck, bundleidcheck, droppedpositivecheck #6, jsonparitycheck R1, forrootlegendcheck arm2, forbudgetmonotoncheck #1/#5, legendcoveragecheck (E), ownerhopcheck (R). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
joyful-ii-V-I
pushed a commit
that referenced
this pull request
Oct 21, 2026
M1 (review rv-hrr, CI run on 051101f): (a) serialize.h headRoundRobinOrder: read mayOpen(0) once above the loop; the ENSURES no longer calls a functor (contracts have no side effects). (b) forbudgetmonotoncheck #1/#5: rule-4 twins under RIPWIRE_NO_HEAD_RR=1, plus #1h/#5h: with the reorder on, the explicit ceiling serves exactly the default's rows as a set (softbudget.py set_prefix). (c) receiverevidencecheck hopnotproven: the hop-candidate r= premise reads the RIPWIRE_NO_HEAD_RR=1 twin (hops walk score order), stated under rule 4. (d) mcpverbscheck: accept <sigs[ >] (the tag may carry files_first=). (e) fixedbufsweep: nb row 7 -> 8 and pin 363/248/248 -> 364/249/249 for the files_first= site (35 B worst case, one size_t). (f) one isDocRow lambda per dialect feeds both the head round-robin's mayOpen and reorderDocsAfterCode: the 2 new Lang::Markdown compares are gone (langidentitycheck 348 -> 346, ceiling unchanged). (g) enumtablecheck stale kDocTierTags: a filter.h comment "types/*.d.ts" opened a block comment for the scanner and hid the exempted table; reworded, the exemption matches again. M2: filter.h declarationTwinFileMultipliers counts a file as implementation evidence only when its path tier is 1.0, its basename is not a row manifest, and it is not a declaration-test suffix (.test-d.ts etc., TS row data). forheadrrcheck H6t/H6p/H6q red on 051101f, green here. CHANGELOG: S1-S3 wording and final numbers (19 gained, 3.96 -> 8.00). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pt-act
pushed a commit
that referenced
this pull request
Oct 27, 2026
…der, honest (18) Review findings addressed (changes-max, rev-496ad92798c0, all 8): - editcheck.h (#2, correctness): the tower reached --edit-check's group model — lowestNode was filled from members.front(), which no longer arrives id-ascending. Traced every consumer (editpreview, mcpverbs, verbs_quality — all want THE FOCUS, verbs_quality binds it as `focus`), so the field becomes focusNode and editCheckRoundTripSpelling compares CONTAINMENT, not first elements: order-independent by construction. Proved with a mixed-kind two-contract red-control: pre-fix binary degrades the refusal to @file:LINE seeds, post-fix offers canonical ids that all paste back accepted; - model.h (#6): three enumerator-keyed static_asserts pin ordinal AND weight of Method/Section/FuncType together — a reordered SymKind without the matching table permutation is now a build error (house pattern, cf. serialize.h's Unknown==12); - lspcheck arm (18) (redhat-et#8): the def-front clause grepped '"line":9' inside a 260-byte window that a regressed Var-first order also satisfied — replaced by file-anchored offset comparison like its ws/symbol sibling. Red-control on the base binary's real regressed bytes: old clause PASS (the flaw), new clause FAIL; - graph.h (#3): the local under the rewritten contract is `towerFront`, not `lowest`; - .ripwire_quality_acks (#1): runLsp complexity/verbosity rows now name the actual growth (the answer-struct destructure + notice branch), the concat-shape argument stays only where it belongs; - graphlegend.h, lsp.h comment split, verbs_report.h (#4/#5/redhat-et#7): the remaining distant voices of the tower — the CLI --owners twin now matches its MCP sibling. Gates: 18/18 targeted file-sweep ALL PASS in the leap-build container (lspcheck editcheck family x5 decltodef incl. compile-driver compact/ legend budget x2 docanchor owners mcp x3 connect affected attribmultidef); determinism x2; map byte-IDENTICAL vs the b59b082 base binary; xmllint clean; editpreviewcheck green on the parallel host sweep. Co-Authored-By: Claude <noreply@anthropic.com> Authored by @mpapis with AI assistance (DeepSeek V4.1 Flash / Qwen 3.8 Flash) under his supervision.
pt-act
pushed a commit
that referenced
this pull request
Oct 27, 2026
…ched to its guards Review findings addressed (changes-max, rev-aae42d3f5c3f, all 6): - graph.h (#2): the --connect tie-break prose still asserted "candidates ascend by id" after C2 — corrected to what the scan does: a strictly better join wins, ties keep the FIRST candidate met, and the arrival order is the tower front for the name/file tier (id-ascending only on the canonical-id/Scope::name tiers); - model.h (#3): the table comment over-claimed — three keyed asserts anchor Method/Section/FuncType ordinals+weights, but a swap of two UNANCHORED enumerators (Var/Interface) would trip none; the claim now says exactly that, guards unchanged; - lspcheck arm (18) (#5): the hover-front clause was an unanchored membership grep over the whole hover — it now asserts the method block offset EQUALS the first def-block offset. Red-control on the base binary's real Var-first bytes: OLD clause PASS (the flaw), NEW FAIL (method=235 vs first=74); green on the current build (74=74); - lspcheck arm (18b) (#6): both 340-byte windows replaced by first-row containment (needle offset >= first row start and < second row start). Honest qualifier recorded: base CANNOT regress this clause (created_at's two defs tie on kind, so id order == tower order there) — the control is base's real Location rows transposed byte-for-byte: OLD window PASS, NEW first-row FAIL; - decltodefcheck (#4): framing paragraph "lowest-id projection" -> "tower-front projection", lockstep with graphlegend.h; - .ripwire_quality_acks (#1): the runLsp complexity/verbosity rows now name their own growth (the defs>1 branch), the concat-shape argument stays on the duplication rows it belongs to. Deliberately NOT fixed this round (parked for the next review to judge): test/mcphandlecheck.sh prose still says "lowest-id pick" on fetch_body's name path — a gate outside this branch's touched set. Gates: one container build (BUILD_EXIT=0); BOTH the fixer's and the loop-owner's independent sweeps agree — lspcheck, decltodefcheck (incl. the compile-driver arm), compactlegendcheck, connectcheck, connectcorecheck (with its ASan/UBSan arm), editcheckcheck: ALL PASS; determinism x2; map byte-IDENTICAL vs the b59b082 base snapshot; xmllint clean. Co-Authored-By: Claude <noreply@anthropic.com> Authored by @mpapis with AI assistance (DeepSeek V4.1 Flash / Qwen 3.8 Flash) under his supervision.
pt-act
pushed a commit
that referenced
this pull request
Oct 27, 2026
…premise-pinned arms Review findings addressed (changes-max, rev-bedff612f3c0, all 7): - verbs_report.h (#2, warning): the EMITTED --owners legend still taught "the FIRST of them (lowest node id)" while both sibling copies of the sentence had been fixed around it — now the tower front (kind, leading language, lowest id), ownerscheck's pinned needles re-pinned lockstep; - graph.h (#1): declToDefFollowThrough's comment claimed its ascending sort is a caller contract — applyNameTower re-orders the tier two lines later at the only call site; the comment now says what is true: the sort makes the widening's own output deterministic BEFORE the tower orders the tier (the sort itself untouched); - decltodefcheck (#4): E3 framing + echoed E3d title moved to the tower-front language, finishing the file's stale-pick-rule walk; - lspcheck arms (#5, #6): the (19) single-def control now pins its own premise (the hovered answer must exist before asserting the sentence's absence — it PASSed on an absent answer before); the (20) parity arm states the kLspHoverUseCap=8 premise against the capped hover tier. Red-controls: OLD (19) control PASSes the base binary's null-answer bytes, NEW FAILs them; #6's grown-copy hover is named by premise, not misdiagnosed as parity failure; - mcphandlecheck (redhat-et#7): wording-only per loop-owner decision (the campaign's C3 scope names the MCP descriptions lane) — comments and arm-title strings, zero assertion changes; - compactlegendcheck (#3): the safe-delete row's measured 828 -> 830 attributed to e5d39f7's +2 B clause (9 B -> 11 B tower-front match), pin 840 unchanged — the table's own re-pin-in-the-commit-that-adds- bytes rule. Gates: one container build (BUILD_EXIT=0); owner sweep — lspcheck, ownerscheck, decltodefcheck, compactlegendcheck (rc=0, ALL PASS on the stable file), mcphandlecheck, mcpverbscheck, mcpmanifestcheck ALL PASS; determinism x2; map byte-IDENTICAL vs the b59b082 base snapshot; xmllint clean. One earlier compactlegendcheck FAIL was proven transient: a released continuation edited the script mid-run (bash reads scripts incrementally) — reproduced rc=0 in-container afterwards. Co-Authored-By: Claude <noreply@anthropic.com> Authored by @mpapis with AI assistance (DeepSeek V4.1 Flash / Qwen 3.8 Flash) under his supervision.
pt-act
pushed a commit
that referenced
this pull request
Oct 27, 2026
…hey describe Final round under the loop's 5-iteration cap. Four findings (changes-max, rev-96d8ae4ba475, all confirmed, all prose-class), all fixed: - editcheck.h (#1): the focusNode comment claimed "the focus resolveFocus would pick" — false at one site: resolveFocus carries the bodyless C/C++ yield, so a same-file prototype+def group's front is the prototype while the yield picks the bodied member. Now states the exact relation (same node except where the documented yield moves the pick) — verified against the resolveFocus body and the emitted legend, which already carry the two rules separately; - mcpverbs.h (#2): "Post-C2"/"pre-C2" dated the union's tower move to the wrong lane — the harvest-card C2 is a different change entirely (every other C2 in the touched files means that card correctly). Reworded to name the mechanism: once the name tier took the tower, the union's pre-tower lowest-id pick moved with it; - lspcheck (#3): arm (18b) prose (and the header line) said column clicks resolve to "db/schema.rb" — the fixture's schema.rb sits at the collision-tree root; repo sweep shows the remaining db/schema.rb mentions are all legitimate; - ownerscheck (#4): the paragraph tail iteration 4's head-rewrite left stale, now reads the tower-front rule once, coherently. Gates: one container build (0 errors; comment edits recompile the main TU — the compile gate itself); editcheckcheck, lspcheck, ownerscheck ALL PASS in-container on the relinked binary; determinism x2; map byte-IDENTICAL vs the b59b082 base snapshot. Diff is prose-only: 4 files, +16/−11, zero behavior lines. Loop status: five iterations, findings 7/8/6/7/4, all fix-set items fixed (30 across the run), DISCUSS accumulator empty throughout, churn guards 10/10 monotonic. The loop now stops at its cap; this commit was verified by the full gate protocol but has not itself been re-reviewed. Co-Authored-By: Claude <noreply@anthropic.com> Authored by @mpapis with AI assistance (DeepSeek V4.1 Flash / Qwen 3.8 Flash) under his supervision.
pt-act
pushed a commit
that referenced
this pull request
Oct 27, 2026
…nd generated figures A non-zero git exit (no repo, no HEAD) now makes the whole-tree hunk read 'no evidence' (change_set shows evidence=0) instead of an empty measurement (CodeRabbit #1). The PR's CHANGELOG entry lives in changelog.d/ now, credits @llvm-x86 and states the new fallbacks. Legend dictionary figure regenerated (dictv a612d2cf, 923 entries). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds arms (6b)/(6c) to
test/mcpverbscheck.sh(L4 section, right after thepack_task-absent assertion — reuses the in-scopel4_field/LIST_OUT2, no second server spawn):tools/list. ANY add/remove/rename reddens until a human updatesEXPECTED_VERBSconsciously.run_traceinjected into the live list must disturb the comparison, guarding the vacuous-arm shape), plus a named tripwire asserting no shell/exec-shaped verb is advertised:--run-tracestays CLI-only (runtracecheck.showns the CLI side).Why
The existing
L4_COUNT==31arm fails closed on a verb added, and the per-name arms pin the L4/field-notes verbs individually — but a rename or swap that keeps the count at 31 and touches a verb no arm names (analyze,grep, the edit trio, …) passes every existing arm. That's CONTRIBUTING §2 shape 7 ("true but narrower"): "same count + these names present" is strictly weaker than "the roster is exactly this set". A verb that reaches a subprocess (a hypotheticalrun_traceMCP twin of the CLI-only--run-trace) could replace an unnamed read verb with every existing arm green.Context
Follow-up to a security audit. Both audit findings closed clean:
jsonesc::escapeHtml\uXXXX-escapes<>&at emission, and all 8innerHTMLsinks escape repo-derived values viaescHtml()or interpolate integers/constexpr vocabularies; node detail usestextContent. Repro'd by indexing a fixture repo with<img src=x onerror=alert(1)>in a filename — payload appears in the emitted file only as\u003c…\u003e.--run-tracereachable from MCP) — never a vuln: no such verb exists;from_traceparses pasted text and executes nothing. This PR is invariant-hardening so that stays true, not a vuln fix.Verification (real build, g++ 13.3 / cmake 4.4)
tools/listroster from the built binary matches the pinned set exactly (31 verbs, sorted, byte-for-byte).lego→run_traceinkMcpVerbTable+ thetools/liststanza (constant-count swap) and rebuilt:Reverted the plant; gate is
ALL PASSwith the new arms green.manifestcheckrc=0,gatecountcheckrc=0 — new arm in an existing gate file, so noregression.sh/ gate-count ride-along.Known, pre-existing, unrelated
readmedriftcheckis red on this fork'smainalready (docs/LINEAGE.md prose-vs-table enumeration, 13 FAILs) — verified identical with and without this change (stash/pristine rerun). Disclosed here so CI's red on that gate isn't misread as caused by this PR. Local full-suite runs in this sandbox also include env-dependent failures (no network); CI is the adjudicator.