Skip to content

refactor(pair2-mcp): polish tail — 4 follow-on beads (rf2-b05ld)#1027

Merged
mike-thompson-day8 merged 3 commits into
mainfrom
refactor/rf2-pair2-tail-polish
May 14, 2026
Merged

refactor(pair2-mcp): polish tail — 4 follow-on beads (rf2-b05ld)#1027
mike-thompson-day8 merged 3 commits into
mainfrom
refactor/rf2-pair2-tail-polish

Conversation

@mike-thompson-day8
Copy link
Copy Markdown
Contributor

Summary

Four follow-on beads landed atop the rf2-pair2-batch (#1016) polish cluster — all
on the tools/pair2-mcp/ surface.

  • rf2-c0h8p — merge-drain + drain-produced-output? unit tests (subscribe
    streaming loop). 11 tests pinning the state-merge contract; lifted both to
    public so the test ns can pin directly.

  • rf2-lhue6 / rf2-n5j96 — cosmetic polish / trivials cluster:

    • merge-drain exposed as public; drain-produced-output? predicate single-
      sources the tick-gate contract across the merge-state path and the emit gate.
    • nrepl/attach-handlers! data callback folds buf-concat + frame-split into
      one atomic swap! (NR1) — closed a race window where a second data event
      could double-decode the same frame.
    • read-edn-safe logs to stderr on catch (NR2) — silent parse failures now
      surface in the dev console.
    • precheck/precheck-frameprecheck/precheck-target returning a tagged
      2-tuple ([:explicit <kw>] / [:operating-frame nil]); sentinel keyword
      (:rf.mcp.cache/operating-frame) gone.
    • wire/default-build-id cached in a delay at namespace load — was 11+
      env-var reads per tool dispatch (T5).
    • New wire/arg-keyword helper folds the (some-> (wire/arg ...) keyword)
      pattern across five tool bodies (T18).
    • args/parse-modes-arg JS-object discriminator collapses to object? (ARGS1).
    • args/parse-frames-arg typo-swallow behaviour documented (ARGS3).
    • tail-build 300ms soft-delay + 100ms poll cadence lifted to named defs.
  • rf2-agcq2 / rf2-kaof4 — spec amendments:

    • spec/Tool-Pair.md adds a §MCP-side wire-marker vocabulary enumeration
      table — every :rf.mcp/* / :rf.size/* marker the MCP-server layer emits
      listed with mechanism, emit site, and top-level keys.
    • tools/pair2-mcp/spec/003-Tool-Catalogue.md adds §Universal
      :typicalTokens on every tool descriptor.
    • descriptors_data.cljs: drop "legacy" framing on epochs-mode \"full\"
      (it's the time-travel-restore mode, not legacy).
    • sensitive.cljs: trim the defensive ":epochs may inherit in future"
      parenthetical (rf2-isdwf made it current contract).
    • cap.cljs: document the intentional :isError pass-through asymmetry
      vs cache/apply-cache.
  • rf2-uebll — lift causa-mcp wire-pipeline expansions back into pair2-mcp
    Principles per causa-mcp's DESIGN-RATIONALE.md Lock test: CLJS coverage for hierarchical/always/after/invoke machines (rf2-pc82) #9 §Why follow-up:

    • max-tokens / :max-tokens notation pin (the JSON-RPC arg name + parsed
      CLJS keyword pairing is fixed cross-server).
    • Catalogue-entry contract (normative) — every tool entry MUST declare
      which mechanisms apply, the :typicalTokens hint, the cap-reached
      behaviour, and the default knob values.

Deferred (not in this PR)

  • rf2-e35a5 — elision walker returns [v count] from server. Medium-risk
    wire-shape change requiring careful design across snapshot + get-path eval
    forms; deserves its own focused bead session.
  • rf2-w92r8 — perf micro-benchmarks. Separate concerted effort to build
    the benchmark harness; data-driven by design.
  • rf2-9pe31 — O(1) cached app-db-hash accessor. Touches runtime preload
    • frame.cljc; disjoint surface from pair2-mcp polish, separate dispatch.
  • rf2-5ky6c — coord rename for v1.0. Decision-blocked pre-v1.0 per
    causa-mcp Lock test: trace-stream completeness (rf2-91tl) #6.

Test plan

  • cd implementation && npm run test:cljs — 1818/1818 pass.
  • cd implementation && npm run test:bundle-isolation — pass.
  • cd tools/pair2-mcp && npm test — 325/325 pass (+11 new merge-drain
    tests on top of prior 314).
  • python scripts/check_skill_mcp_drift.py — clean.

Mike Thompson added 3 commits May 14, 2026 15:15
…rivials (rf2-b05ld)

Cluster of P2/P3 polish surfaced by the rf2-7hie3 and rf2-b05ld
audits. Each is small enough that none justifies a standalone bead;
batched here so a future contributor reads one diff instead of
twelve.

- subscribe: lift `merge-drain` + new `drain-produced-output?`
  predicate to public; single-source the "what counts as a tick"
  contract across the merge-state path AND the emit gate (was an
  inline OR at two sites). Adds 11 unit tests pinning the state-
  merge contract (rf2-c0h8p).
- nrepl: `attach-handlers!` data-callback folded buf-concat + frame-
  split into one atomic `swap!` — prior two-swap shape left a
  window where a second `data` event could double-decode the same
  frame (NR1 / N2). `read-edn-safe` logs to stderr on catch so
  silent EDN parse failures surface in the dev console (NR2 / N4).
- precheck: replace `:rf.mcp.cache/operating-frame` sentinel
  keyword with a tagged 2-tuple — `[:explicit <kw>]` /
  `[:operating-frame nil]`. `precheck-form` now dispatches on the
  tag, not a magic value. Renamed `precheck-frame` → `precheck-
  target` (CACHE1).
- wire: cache `default-build-id` env-var read in a delay (was
  11+ reads per tool dispatch ⇒ 1 at first call). New `arg-keyword`
  helper folds the `(some-> (wire/arg args :k) keyword)` pattern
  recurring across five tool bodies (T5 / T18).
- args: `parse-modes-arg`'s JS-object discriminator collapses to
  `object?` (ARGS1, -4 LoC). `parse-frames-arg` typo-swallow
  behaviour documented (ARGS3).
- tail-build: lift the 300ms soft-delay + 100ms poll cadence to
  named `def`s (T14).

Quality gates: pair2-mcp test suite green (325/325, +11 merge-
drain tests). implementation cljs gate green (1818/1818).

Refs: rf2-c0h8p, rf2-lhue6, rf2-n5j96.
…mily, descriptor polish (rf2-agcq2, rf2-kaof4)

Two related spec gaps surfaced by the rf2-b05ld / rf2-7hie3 audits;
batched together because both touch the wire-vocabulary surface.

- spec/Tool-Pair.md: add a §MCP-side wire-marker vocabulary
  enumeration table — every `:rf.mcp/*` / `:rf.size/*` marker the
  MCP-server layer emits (cache-hit / overflow / dedup-table /
  diff-from / summary / large-elided / cursor-stale + the
  framework-side :rf/redacted sentinel) listed with mechanism,
  emit site, and top-level keys. Prior wording named two markers
  in passing without enumerating the family.
- tools/pair2-mcp/spec/003-Tool-Catalogue.md: add §Universal:
  `:typicalTokens` on every tool descriptor — the rf2-6sddv slot
  was emitted on every descriptor in `descriptors_data.cljs` but
  not enumerated in the catalogue spec.
- tools/pair2-mcp/src/.../descriptors_data.cljs: drop the
  "legacy" framing on `epochs-mode "full"`. The mode is the
  time-travel-restore mode — describing it as "legacy" mislabels
  current contract. Wire shape unchanged.
- tools/pair2-mcp/src/.../sensitive.cljs: trim the defensive ":epochs
  may inherit in future" parenthetical on `scrub-snapshot-sensitive`
  — epoch-record stamping is current contract per rf2-isdwf, not a
  future possibility.
- tools/pair2-mcp/src/.../cap.cljs: document the intentional
  `:isError` pass-through asymmetry vs `cache/apply-cache`.
  `apply-cache` short-circuits on `:isError` (transient failures
  must not poison the cache); `apply-cap` measures and (if over
  budget) wraps an error like any other payload (oversize bytes
  are oversize bytes regardless of success / failure).

Quality gates: pair2-mcp tests green (325/325).

Refs: rf2-agcq2, rf2-kaof4.
… max-tokens pairing + catalogue-entry contract (rf2-uebll)

Causa-MCP's DESIGN-RATIONALE.md Lock #9 §Why promised a follow-up
alignment bead to lift wire-pipeline expansions back into pair2-mcp
Principles wording where the two servers converge. Cross-server
posture: agents "learn the slot on one server, get the same slot
on the others", so pair2-mcp's spec wording matches causa-mcp's
where the two converge.

Two normative additions to §Tight token budget per response §The
wire-boundary cap:

- **`max-tokens` / `:max-tokens` notation pin** — the arg name is
  fixed cross-server. `max-tokens` is the JSON-RPC `arguments` key
  (string, kebab-case, the wire shape an agent host sends);
  `:max-tokens` is the parsed CLJS keyword inside the runtime.
  Pair2-mcp, story-mcp, and causa-mcp all parse the same wire slot
  to the same in-process key.

- **Catalogue-entry contract (normative)** — every tool entry in
  003-Tool-Catalogue.md MUST declare: (1) which of the eight
  mechanisms apply, (2) the `:typicalTokens` hint, (3) the
  cap-reached behaviour, (4) default mode / limit / dedup /
  elision values. Aligns with causa-mcp's catalogue-entry contract
  so agent per-tool budget projections work uniformly across both
  servers.

Path slicing (mechanism 2), structural dedup (mechanism 5),
:rf.mcp/overflow and :rf.mcp/summary shapes are already
documented at pair2-mcp Principles §Path slicing / §Structural
dedup / §The wire-boundary cap — no change needed.

Quality gates: pair2-mcp tests green (325/325).

Refs: rf2-uebll. Resolves causa-mcp DESIGN-RATIONALE Lock #9
§Why follow-up commitment.
@mike-thompson-day8 mike-thompson-day8 merged commit 25d9ab5 into main May 14, 2026
35 checks passed
@mike-thompson-day8 mike-thompson-day8 deleted the refactor/rf2-pair2-tail-polish branch May 14, 2026 05:41
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.

1 participant