Every ticket as the root of its provenance graph — goal, patch, approval, runs and (as the ticket-class build lands) mandate, manifestations, guarantees, journey, artifacts and children. Rendered through the <<<TicketGraphList>>> tag.
goal
Rewrite ONE unique forge module as entirely new, behavior-preserving, installable,
control-config'd Python, per the FORGE-wide refactor standard #200 (#std).
This ticket covers ONE module — the one identified below — and nothing else. It was filed
against the module's DEDUPLICATED identity, so if that module was copy-pasted across the
forge, every copy is covered by this single ticket.
MODULE KEY : forge-rw:5bda83c2edbfad97
(the ticketer's idempotency marker — it lives in this ticket's TITLE. Do
not edit the title, or the module will be re-filed as a duplicate.)
IDENTITY : AST-NORMALIZED — codebean's `_ast_norm` (#183), i.e.
ast.dump(ast.parse(ast.unparse(ast.parse(src)))).
Copies of this module that differ only in comments, blank lines,
quoting or spacing carry the SAME module-sha and are covered by THIS
ticket. A differing docstring is real content, so a module whose
docstring differs is a DIFFERENT module with its own ticket.
SIZE : 5162 bytes
EXTENSION : .py
CANONICAL SOURCE (the location this ticket is named for):
repo : agent_tools_suite
path : coupler.py
ref : HEAD (HEAD)
blob : 5ae87e7885b46adee7dd0bc1af953fe14b6fff34 (git blob sha1)
REFERENCE ONLY — you do NOT need this command. This module's bytes are embedded
COMPLETE in THE ORIGINAL SOURCE block below, and that is what the rewrite is based
on. For a reader who does have forge access:
git --git-dir=/Users/stevenpeterson/code/installed/jazz-project/config/forge/remotes/agent_tools_suite.git cat-file blob 5ae87e7885b46adee7dd0bc1af953fe14b6fff34
THE SAME MODULE ALSO LIVES AT THESE FORGE TIPS: none — this module is unique to
agent_tools_suite among the repos scanned so far.
HISTORICAL OCCURRENCES of this exact blob — every OTHER DISTINCT {repo, path}
the omni-git index (`occ`, joined on the git blob sha1) records this
byte-identical file at, with the index's own `ts` for the first row of each.
Any place this run enumerated LIVE is listed under the forge tips above, not
here. Context for the rewrite, not extra work:
testmonkeyalpha-group/jazz-forge/agent_tools_suite:coupler.py [occ.ts gitlab]
THE ORIGINAL SOURCE, EMBEDDED — YOU NEED NO FORGE ACCESS TO DO THIS TICKET.
The module's own bytes are reproduced below, inside this ticket. THEY are the
authoritative copy and the behavior-preserving basis: rewrite from them. The
`git --git-dir=... cat-file blob` command under CANONICAL SOURCE above is kept only as a
REFERENCE for a reader who happens to have forge access — running it is NOT part of this
ticket. (Why the bytes are here at all: the pair_loop worker that executes this ticket is
sandboxed to the ticket's own congruency worktree and cannot read the forge's bare repos.
Ticket #346 is the fix that put them on the ticket.)
The block BEGINS at the line
===ORIGINAL SOURCE (verbatim, the behavior-preserving basis)===
and ENDS at the first line
===END SOURCE===
Everything strictly between those two lines is the module — 5162 byte(s), byte for byte, with no re-indentation, no re-wrapping and nothing
elided.
===ORIGINAL SOURCE (verbatim, the behavior-preserving basis)===
#!/usr/bin/env python3
"""coupler — a zero-dependency MCP aggregator. Owned by the gate.
Fronts N downstream MCP servers as one: spawns each, aggregates every tool into a
single list namespaced `<server>__<tool>`, and routes each call to the owning
downstream. A dead downstream is isolated, never sinking the coupler.
Downstreams come from the `servers` block of registry.json (paths relative to this
dir). Meta tools: coupler__status, coupler__reconnect.
"""
import fnmatch
import os
import re
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import mcplib # noqa: E402
NS = "__"
def load_servers():
raw = mcplib.load_registry(HERE)
return raw.get("servers") or raw.get("mcpServers") or {}
def sanitize(s):
return re.sub(r"[^A-Za-z0-9_-]", "_", str(s))
class Coupler:
def __init__(self):
self.downstreams = {}
self.connected = False
self.toolmap = {} # namespaced name -> (downstream, original name)
self._build()
def _build(self):
self.downstreams = {}
self.filters = {}
for name, spec in load_servers().items():
self.downstreams[name] = mcplib.Downstream(name, spec, HERE)
if spec.get("only") or spec.get("exclude"):
self.filters[name] = {"only": spec.get("only"), "exclude": spec.get("exclude") or []}
self.connected = False
def _allowed(self, server_name, tool_name):
"""Registry-driven per-downstream tool filter: `only` (allowlist of exact tool
names) and/or `exclude` (denylist of fnmatch globs, e.g. `vm_*`)."""
f = self.filters.get(server_name)
if not f:
return True
only = f.get("only")
if only is not None and tool_name not in only:
return False
for pat in f.get("exclude") or []:
if fnmatch.fnmatch(tool_name, pat):
return False
return True
def connect(self):
if self.connected:
return
for d in self.downstreams.values():
d.start()
self.connected = True
META = [
{"name": "coupler" + NS + "status",
"description": "[coupler] Health of every coupled downstream server and its tool count.",
"inputSchema": {"type": "object", "properties": {}, "additionalProperties": False}},
{"name": "coupler" + NS + "reconnect",
"description": "[coupler] Tear down and re-spawn all downstream servers, then re-aggregate.",
"inputSchema": {"type": "object", "properties": {}, "additionalProperties": False}},
]
def list_tools(self):
self.connect()
tools = list(self.META)
self.toolmap = {}
for d in self.downstreams.values():
if d.dead:
continue
for t in d.tools:
if not self._allowed(d.name, t["name"]):
continue
ns = "%s%s%s" % (sanitize(d.name), NS, t["name"])
self.toolmap[ns] = (d, t["name"])
nt = dict(t)
nt["name"] = ns
nt["description"] = ("[%s] %s" % (d.name, t.get("description", ""))).strip()
tools.append(nt)
return tools
def status_text(self):
lines = []
total = 0
for d in self.downstreams.values():
if d.dead:
state = "✗ down (%s)" % (d.error or "unknown")
elif d.proc is not None:
shown = sum(1 for t in d.tools if self._allowed(d.name, t.get("name", "")))
hidden = len(d.tools) - shown
state = "✓ up, %d tools%s" % (shown, (" (%d hidden)" % hidden) if hidden else "")
total += shown
else:
state = "· not started"
lines.append("- %s: %s" % (d.name, state))
body = "\n".join(lines) or "(no servers configured)"
return "## coupler status — %d server(s), %d live tool(s)\n\n%s" % (len(self.downstreams), total, body)
def call_tool(self, name, args):
if name == "coupler" + NS + "status":
self.connect()
return mcplib.text_result(self.status_text())
if name == "coupler" + NS + "reconnect":
for d in self.downstreams.values():
d.stop()
self._build()
self.connect()
return mcplib.text_result(self.status_text())
self.list_tools() # ensure the map reflects live downstreams
entry = self.toolmap.get(name)
if not entry:
return mcplib.text_result('unknown tool "%s". Call tools/list for the current set.' % name, True)
d, original = entry
if d.dead:
return mcplib.text_result("downstream '%s' is down (%s). Try coupler%sreconnect." % (d.name, d.error, NS), True)
try:
return d.call_tool(original, args)
except Exception as e:
return mcplib.text_result("downstream '%s' failed on %s: %s" % (d.name, original, e), True)
_c = Coupler()
mcplib.Server("mcp-coupler", "1.0.0", _c.list_tools, _c.call_tool).serve()
===END SOURCE===
THE CALLABLE SURFACE — every callable in the original, lowered with codebean's
`lower_node` (#183). The rewrite must present THIS surface (same names, same
parameters, same defaults) so callers of the original keep working:
load_servers()
sanitize(s)
Coupler.__init__(self)
Coupler._build(self)
Coupler._allowed(self, server_name, tool_name)
Coupler.connect(self)
Coupler.list_tools(self)
Coupler.status_text(self)
Coupler.call_tool(self, name, args)
CAPTURED BEHAVIORAL EXEMPLARS: none. no function in this module is minable — criteria_miner mines only
self-contained pure functions (it refuses anything that mentions a
world-touching or non-deterministic name, plus methods and no-arg
functions), and nothing here qualified
This does NOT weaken the ticket's bar — it MOVES the work: you must write the
equivalence exemplars by hand from the original's behavior before rewriting, and
they are what settles this ticket.
THE STANDARD — #200's four requirements, which this ticket exists to enforce. All four are
the standard's own words; none is optional:
1. BEHAVIOR-PRESERVING, VERIFIED NOT ASSERTED — the deliverable is ENTIRELY NEW source
code (rewritten, not copied). It must reproduce the ORIGINAL's behavior, and the proof
is the exemplars above (captured via codebean lower_* #183 + criteria_miner
IO-exemplars, exactly as #200 specifies).
2. A PYTHON MODULE — regardless of the source language. This module's source is `.py`;
the rewrite is Python either way.
3. INSTALLABLE — a proper package: pyproject.toml, `pip install -e .` works, console
entry points where applicable. WRITE ONLY YOUR OWN MODULE FILE at
forge2/<repo>/<module>.py. Do NOT hand-author pyproject.toml or __init__.py: the
harness DERIVES them ADDITIVELY from the modules present (congruency/tools/
forge_package.py, #410 — the analogue of the tag-registry fix #281), so your unit never
conflicts with, or clobbers, a sibling module of the same forge2/<repo>/ package. A
package-level pyproject includes every .py in the directory, so your module installs
and imports as `<repo>.<module>` the moment it lands.
4. CONTROL-CONFIG'D — NO hardcoded paths or params. A JSON/registry config object drives
it (the install.json / registry.json idiom of this repo), and per note-for-claude a
tool that cannot see its config THROWS rather than guessing a default. Add ONLY your
own `forge2.<repo>.<module>` section to the package's registry.json (create the file if
it is absent); NEVER read, edit or drop a sibling module's section — the sections are
disjoint keys and stay additive that way.
ACCEPTANCE (#200's, per rewrite ticket) — this ticket settles when ALL of:
a. the new source reproduces every captured exemplar above, plus the edge cases you add
for what sampling cannot reach (paste the runs as evidence);
b. it presents the callable surface above, so existing callers keep working;
c. `pip install -e .` installs it clean from its own pyproject.toml;
d. it runs off a config object with ZERO hardcoded settings, and throws without one.
Kind is `build` (a pair: coder + adversarial tester). This ticket hangs off #200 by a
`spawned` edge, so a stop ticket aimed at #200 brakes every rewrite in this programme.
Filed mechanically by checkouts/current/congruency/tools/forge_refactor_ticketer.py under ticket #201, from the forge bare repos at
/Users/stevenpeterson/code/installed/jazz-project/config/forge/remotes. Its original source is embedded above (#346), so this ticket is complete on its own.