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:e63eaa8c7c306f03
(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 : 19522 bytes
EXTENSION : .py
CANONICAL SOURCE (the location this ticket is named for):
repo : agent_tools_suite
path : crankd.py
ref : HEAD (HEAD)
blob : 2d7fa16472882af65efb8aca792ad98ab500585d (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 2d7fa16472882af65efb8aca792ad98ab500585d
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 (omni-git `occ`): none to add — either the index has no
row for this blob (it is newer than the index's last snapshot, or the index does
not cover its repo), or every place it records is already listed live above.
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 — 19522 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
"""crankd — the crank service. The ONLY thing that runs a crank.
The agent never spawns a crank; it POSTs here. crankd verifies that the crank's ticket carries a valid
WALLET signature over the ticket's CONTENT (unforgeable by the agent — it has no wallet), then runs the
crank as ITS OWN child process, off the agent's process tree, and records provenance. Because the agent
has no subprocess capability at all and crankd only runs wallet-approved cranks, the escape (a crank
subprocess reaching back into the agent's ~/.claude / permission layer) has no path.
POST /crank {"component": "...", "intent": "..."} -> verify approval -> run -> {ok, stdout_tail}
GET /digest?component=... -> the digest a human must wallet-sign
GET /health
env: CONGRUENCY_URL (default :8899), CRANK_APPROVER_PUBKEY (ssh-ed25519 ... of wallet 'crank-approver'),
CONGRUENCY_API_KEY (X-Api-Key for provenance writes). Secrets are read from ~/.secrets/ats.env.
Follow-on isolation (not yet): run the crank under a separate user / the workstation VM so even an
approved crank cannot touch the operator's home. Today it runs as crankd's child (off the agent tree),
which already removes the agent-owned-subprocess escape; congruency patches stay audit-veto-confined
inside mint_crank.
"""
import hashlib
import json
import os
import re
import subprocess
import sys
import tempfile
import threading
import urllib.error
import urllib.request
from datetime import datetime, timezone
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from urllib.parse import parse_qs, urlparse
from cryptography.hazmat.primitives.serialization import load_ssh_public_key
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import crank_discipline # the audit-veto (run_confined) used to apply the approved patch # noqa: E402
HOST = os.environ.get("CRANKD_HOST", "127.0.0.1")
PORT = int(os.environ.get("CRANKD_PORT", "8812"))
CONG = (os.environ.get("CONGRUENCY_URL") or "http://127.0.0.1:8899").rstrip("/")
def _secret(name):
"""Read a value from ~/.secrets/ats.env (KEY=VALUE), else the process env; None if absent."""
path = os.path.expanduser("~/.secrets/ats.env")
if os.path.isfile(path):
for line in open(path):
line = line.strip()
if line.startswith(name + "="):
return line.split("=", 1)[1]
return os.environ.get(name)
APPROVER_PUBKEY = _secret("CRANK_APPROVER_PUBKEY") # ssh-ed25519 pubkey of wallet 'crank-approver'
CONGRUENCY_KEY = _secret("CONGRUENCY_API_KEY")
# component -> how to crank it. The crank runs as crankd's child, in the component's repo.
COMPONENTS = {
"workstation": {
"repo": os.path.expanduser("~/code/workstation"),
"argv": lambda intent: [sys.executable, "install.py", "--mint", "-m", intent],
"version": lambda repo: json.load(open(os.path.join(repo, "install.json"))).get("version", "0.0"),
},
"congruency": {
# crankd applies the agent's patch (audit-veto), then mint_crank --no-patch captures it as the
# next version-4.0NN (self-hosting: make_state snapshots the live db to forge, shadow gate, tag).
"repo": os.path.expanduser("~/code/congruency"),
"argv": lambda intent: ["python3", "checkouts/current/congruency/tools/mint_crank.py",
"--no-patch", "-m", intent],
"version": lambda repo: json.load(open(os.path.join(repo, "install.json"))).get("version", "0.0"),
},
}
_crank_lock = threading.Lock() # serialize: one crank at a time
class CrankError(Exception):
def __init__(self, status, message):
self.status = status
super().__init__(message)
def _now():
return datetime.now(timezone.utc).isoformat()
def _cong(method, path, obj=None):
data = json.dumps(obj).encode() if obj is not None else None
headers = {"Content-Type": "application/json"}
if CONGRUENCY_KEY:
headers["X-Api-Key"] = CONGRUENCY_KEY
req = urllib.request.Request(CONG + path, data=data, method=method, headers=headers)
with urllib.request.urlopen(req, timeout=5) as r:
return json.loads(r.read().decode() or "{}")
def fetch_ticket(component):
"""The component's latest ticket (incl. approval_sig) via the congruency named route, or None."""
rows = _cong("GET", "/?route=ticket.approval&component=%s" % component).get("rows") or []
return rows[0] if rows else None
def digest(ticket):
"""The canonical content digest a human signs — binds id+component+title+body, so any post-approval
edit to the ticket invalidates the signature (defeats bait-and-switch)."""
canon = "\n".join(str(ticket.get(k, "")) for k in ("id", "component", "title", "body", "patch"))
return hashlib.sha256(canon.encode()).hexdigest()
def verify_approval(ticket):
"""True iff ticket.approval_sig is a valid wallet signature over digest(ticket)."""
if not APPROVER_PUBKEY or not ticket.get("approval_sig"):
return False
try:
pub = load_ssh_public_key(APPROVER_PUBKEY.encode())
pub.verify(bytes.fromhex(ticket["approval_sig"]), digest(ticket).encode())
return True
except Exception: # noqa: BLE001 — bad sig / bad hex / wrong key all mean "not approved"
return False
def apply_patch(patch_src, repo):
"""Apply the approved patch under the audit-veto (confined to the repo — no shell-out / out-of-repo
writes), off the agent's process tree. Raises CrankError(403) on escape."""
with tempfile.TemporaryDirectory() as d:
patch_file = os.path.join(d, "patch.py")
with open(patch_file, "w") as fh:
fh.write(patch_src)
try:
return crank_discipline.run_confined(patch_file, repo)
except crank_discipline.CrankRefused as e:
raise CrankError(403, "patch refused by the audit-veto: %s" % e)
def _version_tuple(v):
return tuple(int(x) for x in str(v).split(".") if x.strip().isdigit())
def current_version(component):
try:
return COMPONENTS[component]["version"](COMPONENTS[component]["repo"])
except Exception: # noqa: BLE001
return "0.0"
def fetch_policy(component):
rows = _cong("GET", "/?route=policy.active&component=%s" % component).get("rows") or []
return rows[0] if rows else None
def policy_digest(policy):
"""The canonical digest the human wallet-signs for a standing policy."""
canon = "\n".join(str(policy.get(k, "")) for k in ("component", "max_version", "expires"))
return hashlib.sha256(canon.encode()).hexdigest()
def policy_allows(component):
"""True iff a wallet-signed standing policy covers this crank: valid signature, not expired, and the
component's current version is still below the policy's max_version. The audit-veto still confines
every patch, so this bounds WHICH cranks run autonomously, not what a patch may do."""
if not APPROVER_PUBKEY:
return False
policy = fetch_policy(component)
if not policy or not policy.get("sig"):
return False
try:
load_ssh_public_key(APPROVER_PUBKEY.encode()).verify(bytes.fromhex(policy["sig"]),
policy_digest(policy).encode())
except Exception: # noqa: BLE001
return False
expires = policy.get("expires") or 0
if expires and datetime.now(timezone.utc).timestamp() > float(expires):
return False
return _version_tuple(current_version(component)) < _version_tuple(policy.get("max_version", "0"))
def _shadows(repo):
"""The shadow files declared in the repo's install.json (empty list if unreadable)."""
try:
return json.load(open(os.path.join(repo, "install.json"))).get("shadows", [])
except Exception: # noqa: BLE001
return []
def _harvest_guarantees(ticket_id, repo, version, new_shadows):
"""For each shadow this crank INTRODUCED, run it and record its green ✓ labels as guarantees
attributed to the ticket. Applies the author's declared bindings (binding.list) so each guarantee's
clause_seq is set where declared (else unbound). Best-effort; never raises. Returns count recorded."""
binds = {} # declared guarantee-label -> clause_seq
try:
rows = _cong("GET", "/?route=binding.list&ticket_id=%s" % ticket_id).get("rows") or []
binds = {r["guarantee_label"]: r["clause_seq"] for r in rows}
except Exception: # noqa: BLE001
pass
n = 0
for shadow in new_shadows or []:
try:
r = subprocess.run([sys.executable, shadow], cwd=repo, capture_output=True, text=True, timeout=120)
except Exception: # noqa: BLE001
continue
if r.returncode != 0: # only harvest a shadow that held green
continue
for line in r.stdout.splitlines():
line = re.sub(r"\x1b\[[0-9;]*m", "", line).strip()
if not line.startswith("✓"):
continue
g = line[1:].strip()
dig = hashlib.sha256(("%s|%s|%s" % (ticket_id, shadow, g)).encode()).hexdigest()
try:
_cong("POST", "/?route=guarantee.record",
{"ticket_id": int(ticket_id), "version": version, "shadow": shadow,
"guarantee": g, "clause_seq": binds.get(g), "digest": dig})
n += 1
except Exception: # noqa: BLE001
pass
return n
def _run_shadows_green(repo):
"""Run every shadow declared in the repo and collect the green ✓ labels it CURRENTLY asserts —
the candidate contract this crank would ship."""
green = set()
for shadow in _shadows(repo):
try:
r = subprocess.run([sys.executable, shadow], cwd=repo, capture_output=True, text=True, timeout=120)
except Exception: # noqa: BLE001
continue
if r.returncode != 0:
continue
for line in r.stdout.splitlines():
line = re.sub(r"\x1b\[[0-9;]*m", "", line).strip()
if line.startswith("✓"):
green.add(line[1:].strip())
return green
def _held_guarantees(component):
"""Every guarantee label the component has previously recorded — the contract it must not erode."""
try:
rows = _cong("GET", "/?route=guarantee.held&component=%s" % component).get("rows") or []
return {r["guarantee"] for r in rows}
except Exception: # noqa: BLE001
return set()
def _revert(repo):
"""Undo an applied-but-unminted patch so a refused crank leaves the repo at HEAD (not dirty)."""
for argv in (["git", "checkout", "--", "."], ["git", "clean", "-fd"]):
try:
subprocess.run(argv, cwd=repo, capture_output=True, timeout=30)
except Exception: # noqa: BLE001
pass
def run_crank(component, intent, patch=None):
"""Apply the approved patch (confined), then run the crank — both as crankd's OWN children, off the
agent's process tree. Returns a result dict."""
cfg = COMPONENTS[component]
before = set(_shadows(cfg["repo"])) # shadows before the patch, to spot what it introduces
if patch and patch.strip():
apply_patch(patch, cfg["repo"]) # audit-veto confined; makes the change in the repo
held = _held_guarantees(component) # regression gate: a crank must not DROP a held guarantee
if held:
dropped = held - _run_shadows_green(cfg["repo"])
if dropped:
_revert(cfg["repo"]) # undo the patch — the crank is refused, not minted
raise CrankError(409, "contract regression: %d held guarantee(s) would be dropped: %s"
% (len(dropped), "; ".join(sorted(dropped))[:300]))
result = subprocess.run(cfg["argv"](intent), cwd=cfg["repo"],
capture_output=True, text=True, timeout=900)
if result.returncode != 0:
_revert(cfg["repo"]) # undo the patch — the mint failed, so a retry sees a clean tree
raise CrankError(500, "crank failed (rc=%s): %s"
% (result.returncode, (result.stderr or result.stdout).strip()[-400:]))
return {"ok": True, "component": component, "patched": bool(patch and patch.strip()),
"stdout": (result.stdout or ""), # full output — recorded, then popped from the response
"stdout_tail": (result.stdout or "").strip().splitlines()[-5:],
"new_shadows": [s for s in _shadows(cfg["repo"]) if s not in before]}
def _journal(ticket_id, kind, text):
"""Append a journey event (success/blunder/pivot/note) to a ticket's history. Best-effort."""
if not ticket_id:
return
try:
_cong("POST", "/?route=journey.record", {"ticket_id": int(ticket_id), "kind": kind, "text": text})
except Exception: # noqa: BLE001
pass
def _publish_artifact(ticket_id, version, blob_text, name="workstation-run", kind="run-output"):
"""Store a crank's run-evidence in forge (content-addressed) and reference it on the ticket. forge
addresses by sha256(content), so we compute the sha locally. Best-effort; returns the sha or None."""
if not ticket_id or not blob_text:
return None
sha = hashlib.sha256(blob_text.encode()).hexdigest()
try:
fd, tmp = tempfile.mkstemp()
with os.fdopen(fd, "w") as fh:
fh.write(blob_text)
subprocess.run(["python3", "-m", "forge.cli", "artifact", "put", tmp,
"--name", name, "--version", str(version), "--kind", kind],
cwd=os.path.expanduser("~/code/jazz-forge"), capture_output=True, timeout=60)
os.unlink(tmp)
_cong("POST", "/?route=artifact.record",
{"ticket_id": int(ticket_id), "name": name, "version": str(version),
"forge_sha": sha, "kind": kind})
return sha
except Exception: # noqa: BLE001
return None
def crank(component, intent):
"""The whole gated flow: wallet-approved-ticket check -> run -> provenance. Raises CrankError."""
if component not in COMPONENTS:
raise CrankError(404, "unknown component %r" % component)
if not intent:
raise CrankError(400, "intent required")
ticket = fetch_ticket(component)
if not ticket:
raise CrankError(403, "no ticket for %r — file one first" % component)
approved = verify_approval(ticket) # per-crank wallet signature (manual)
by_policy = policy_allows(component) if not approved else False # standing scope (autonomous)
if not (approved or by_policy):
raise CrankError(403, "ticket %s not authorized: no wallet approval and no covering policy for %s"
% (ticket.get("id"), component))
try:
with _crank_lock:
result = run_crank(component, intent, ticket.get("patch"))
except CrankError as e: # a refused/failed crank is a blunder in the ticket's journey
_journal(ticket.get("id"), "blunder", str(e))
raise
try: # provenance best-effort
_cong("POST", "/?api=memories", {"ts": _now(), "kind": "crank", "component": component,
"intent": intent, "session": "crankd",
"note": "ticket=%s auth=%s" % (ticket.get("id"),
"signature" if approved else "policy")})
except Exception: # noqa: BLE001
pass
result["ticket"] = ticket.get("id")
result["authorized_by"] = "ticket-signature" if approved else "policy"
try: # persist the FULL run (durable history + the source phase-2 harvests guarantees from)
out = result.get("stdout", "")
cfg = COMPONENTS[component]
_cong("POST", "/?route=run.record", {
"component": component, "version": cfg["version"](cfg["repo"]),
"ticket_id": ticket.get("id"), "authorized_by": result["authorized_by"],
"ok": 1 if result.get("ok") else 0,
"shadow_output": out, "digest": hashlib.sha256(out.encode()).hexdigest()})
except Exception: # noqa: BLE001
pass
try: # iteration 5: auto-harvest guarantees from the shadow(s) this crank introduced
cfg = COMPONENTS[component]
result["guarantees"] = _harvest_guarantees(
ticket.get("id"), cfg["repo"], cfg["version"](cfg["repo"]), result.get("new_shadows"))
except Exception: # noqa: BLE001
pass
_journal(ticket.get("id"), "success", # iteration 10: a mint is a success in the journey
"minted %s v%s" % (component, COMPONENTS[component]["version"](COMPONENTS[component]["repo"])))
try: # iteration 11: publish the run evidence to forge, reference it on the ticket
_publish_artifact(ticket.get("id"),
COMPONENTS[component]["version"](COMPONENTS[component]["repo"]), result.get("stdout", ""),
name=component + "-run")
except Exception: # noqa: BLE001
pass
result.pop("stdout", None) # keep the crank response small (tail only)
result.pop("new_shadows", None)
return result
class Handler(BaseHTTPRequestHandler):
def log_message(self, *a): # quiet the default access log
pass
def _send(self, status, obj):
body = json.dumps(obj).encode()
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self):
parsed = urlparse(self.path)
if parsed.path == "/health":
return self._send(200, {"ok": True, "components": list(COMPONENTS), "approver": bool(APPROVER_PUBKEY)})
if parsed.path == "/digest":
component = (parse_qs(parsed.query).get("component") or [""])[0]
ticket = fetch_ticket(component) if component else None
if not ticket:
return self._send(404, {"error": "no ticket for component %r" % component})
return self._send(200, {"component": component, "ticket": ticket.get("id"), "digest": digest(ticket)})
return self._send(404, {"error": "not found"})
def do_POST(self):
if urlparse(self.path).path != "/crank":
return self._send(404, {"error": "not found"})
try:
length = int(self.headers.get("Content-Length") or 0)
body = json.loads(self.rfile.read(length) or "{}")
except Exception: # noqa: BLE001
return self._send(400, {"error": "bad json"})
try:
return self._send(200, crank(body.get("component"), body.get("intent")))
except CrankError as e:
return self._send(e.status, {"error": str(e)})
except Exception as e: # noqa: BLE001
return self._send(500, {"error": "crankd: %s" % e})
def main():
server = ThreadingHTTPServer((HOST, PORT), Handler)
sys.stderr.write("[crankd] http://%s:%d — components=%s approver=%s\n"
% (HOST, PORT, list(COMPONENTS), bool(APPROVER_PUBKEY)))
server.serve_forever()
if __name__ == "__main__":
main()
===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:
_secret(name)
CrankError.__init__(self, status, message)
_now()
_cong(method, path, obj=None)
fetch_ticket(component)
digest(ticket)
verify_approval(ticket)
apply_patch(patch_src, repo)
_version_tuple(v)
current_version(component)
fetch_policy(component)
policy_digest(policy)
policy_allows(component)
_shadows(repo)
_harvest_guarantees(ticket_id, repo, version, new_shadows)
_run_shadows_green(repo)
_held_guarantees(component)
_revert(repo)
run_crank(component, intent, patch=None)
_journal(ticket_id, kind, text)
_publish_artifact(ticket_id, version, blob_text, name='workstation-run', kind='run-output')
crank(component, intent)
Handler.log_message(self, *a)
Handler._send(self, status, obj)
Handler.do_GET(self)
Handler.do_POST(self)
main()
CAPTURED BEHAVIORAL EXEMPLARS — real (input, output) pairs mined from THIS module
with criteria_miner (#200's "verified, not asserted"), running the ORIGINAL as the
oracle. THE REWRITE MUST REPRODUCE EVERY PAIR BELOW, exactly:
current_version(component) — 14 exemplar(s) captured:
current_version('repo') == '0.0'
current_version('version') == '0.0'
current_version('0.0') == '0.0'
current_version(0) == '0.0'
current_version(1) == '0.0'
current_version(-1) == '0.0'
... 8 more exemplar(s) for this function — re-mine them with
criteria_miner.mine() on the source above
_journal(ticket_id, kind, text) — 30 exemplar(s) captured:
_journal('POST', 'POST', 'POST') == None
_journal('POST', 'POST', 'text') == None
_journal('POST', 'POST', '/?route=journey.record') == None
_journal('POST', 'POST', 'kind') == None
_journal('POST', 'POST', 'ticket_id') == None
_journal('POST', 'POST', 0) == None
... 24 more exemplar(s) for this function — re-mine them with
criteria_miner.mine() on the source above
HONEST LIMIT (criteria_miner's own): these cover the SAMPLED inputs, probed
around the function's own branch constants. They are a strong refactor-drift net,
NOT a proof of total equivalence — so treat them as the FLOOR of this ticket's
equivalence evidence and add the edge cases they miss (see ACCEPTANCE).
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.