chaincompiler 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chaincompiler/__init__.py +31 -0
- chaincompiler/bridge.py +36 -0
- chaincompiler/forge.py +59 -0
- chaincompiler/persona.py +157 -0
- chaincompiler/prime.py +41 -0
- chaincompiler/skillpack.py +12 -0
- chaincompiler-0.3.0.dist-info/METADATA +11 -0
- chaincompiler-0.3.0.dist-info/RECORD +10 -0
- chaincompiler-0.3.0.dist-info/WHEEL +5 -0
- chaincompiler-0.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""chaincompiler — the ChainCompiler BASE: the generic compiler-compiler (DESIGN.md §2).
|
|
2
|
+
|
|
3
|
+
This package imports only DOWN (APE + honeyc + rulecatcher). It is the machine the *CC are MADE FROM:
|
|
4
|
+
- forge : the generic "forge a language" core (Language / forge / gate_language / grammar / package_skill)
|
|
5
|
+
- bridge : the HoneyC compile seam + the rulecatcher grammar seam (learn / gate, re-exported from APE)
|
|
6
|
+
- prime : build_prime — the re-injectable prime block
|
|
7
|
+
- skillpack / persona : SKILL.md packaging + the glyph-persona-program compiler
|
|
8
|
+
|
|
9
|
+
ACCC / CORCC / SCCC build ON this base (they import CC). CC NEVER imports the *CC. The Bandit AIOS
|
|
10
|
+
application that orchestrates AC+CoR+SC (construct_language / GBA / HBA / COG) lives ABOVE the *CC in the
|
|
11
|
+
`chainaios` package — it was extracted out of here precisely so this base no longer imports the *CC.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
__version__ = "0.3.0"
|
|
16
|
+
|
|
17
|
+
from .bridge import compile_chain, gate, learn
|
|
18
|
+
from .prime import build_prime
|
|
19
|
+
from .skillpack import skill_markdown, slugify, write_skill
|
|
20
|
+
# the generic compiler-compiler core — the machine the *CC are MADE FROM (DESIGN.md §2). Imports only APE.
|
|
21
|
+
from .forge import Language, forge, gate_language, grammar, package_skill
|
|
22
|
+
# re-export the APE cognition helper the *CC need, so they route through CC (not around it to APE):
|
|
23
|
+
from prompt_engineering import cor_skeleton
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"learn", "gate", "compile_chain", "build_prime",
|
|
27
|
+
"write_skill", "skill_markdown", "slugify",
|
|
28
|
+
# the forge core (ACCC/CORCC/SCCC import these DOWN from here):
|
|
29
|
+
"Language", "forge", "gate_language", "grammar", "package_skill", "cor_skeleton",
|
|
30
|
+
"__version__",
|
|
31
|
+
]
|
chaincompiler/bridge.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""The HoneyC seam (compile a gated chain into lenses) + re-exports of the rulecatcher seam.
|
|
2
|
+
|
|
3
|
+
The rulecatcher seam — `learn` / `gate` / `grammar_lines` / `foreign_tokens` — MOVED DOWN to
|
|
4
|
+
`prompt_engineering.grammar` (REBUILD-SPEC.md §4 — single source of truth, D1). chaincompiler keeps the
|
|
5
|
+
HoneyC-wrapping `compile_chain` (HoneyC is chaincompiler's concern, §6) and RE-EXPORTS the grammar seam,
|
|
6
|
+
so `from chaincompiler.bridge import learn, gate, grammar_lines` and `from chaincompiler import learn,
|
|
7
|
+
gate` stay byte-stable.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from honeyc.normalize import normalize
|
|
12
|
+
from honeyc.parser import parse_text
|
|
13
|
+
from honeyc.render import render
|
|
14
|
+
|
|
15
|
+
# the rulecatcher seam now lives in the base (DOWN edge):
|
|
16
|
+
from prompt_engineering.grammar import (
|
|
17
|
+
ForeignToken,
|
|
18
|
+
foreign_tokens,
|
|
19
|
+
gate,
|
|
20
|
+
grammar_lines,
|
|
21
|
+
learn,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def compile_chain(chain: str) -> dict:
|
|
26
|
+
"""Compile a chain through HoneyC into semantic lenses."""
|
|
27
|
+
program = parse_text(chain)
|
|
28
|
+
return {
|
|
29
|
+
"readable": render(program, "readable"),
|
|
30
|
+
"triples": render(program, "triples"),
|
|
31
|
+
"prose": render(program, "prose"),
|
|
32
|
+
"statements": normalize(program),
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__all__ = ["compile_chain", "learn", "gate", "grammar_lines", "foreign_tokens", "ForeignToken"]
|
chaincompiler/forge.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""forge.py — the generic compiler-compiler core (the "forge a language" move).
|
|
2
|
+
|
|
3
|
+
This is the machine the *CC are *made FROM* (DESIGN.md §2: ACCC/CORCC/SCCC import CC). A forged
|
|
4
|
+
language = a rulecatcher SCOPE holding a ratified grammar; `forge` mints one, `gate_language` enforces it,
|
|
5
|
+
`grammar` reads it back, `package_skill` wraps a compiled body as a publishable `<name>/SKILL.md`. Each
|
|
6
|
+
*CC calls these with its own chain-kind prefix + render/parse and adds nothing to the mechanism.
|
|
7
|
+
|
|
8
|
+
CC imports only DOWN (APE + rulecatcher); it never imports the *CC.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
|
|
14
|
+
from prompt_engineering import write_skill, grammar_lines, learn
|
|
15
|
+
from prompt_engineering.grammar import gate as _gate
|
|
16
|
+
from rulecatcher.db import connect, list_rules
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class Language:
|
|
21
|
+
"""A forged language: a rulecatcher scope holding a ratified grammar."""
|
|
22
|
+
name: str
|
|
23
|
+
scope: str
|
|
24
|
+
db: str
|
|
25
|
+
rule_count: int
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def forge(kind: str, name: str, examples: list[str], *, db: str, strict: bool = False) -> Language:
|
|
29
|
+
"""Mint a `kind` language for `name` from example chains (scope = `<kind>:<name>`).
|
|
30
|
+
|
|
31
|
+
strict=False → learn the SHAPE only (next_kind): any vocabulary is allowed.
|
|
32
|
+
strict=True → also pin the vocabulary (next_token): the gate enforces domain-specific tokens.
|
|
33
|
+
"""
|
|
34
|
+
scope = f"{kind}:{name}"
|
|
35
|
+
rule_types = ("next_kind", "next_token") if strict else ("next_kind",)
|
|
36
|
+
with connect(db) as cx:
|
|
37
|
+
adopted = learn(cx, examples, scope=scope, rule_types=rule_types, label=f"forge:{name}")
|
|
38
|
+
return Language(name=name, scope=scope, db=db, rule_count=len(adopted))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def gate_language(language: Language, candidate: str) -> tuple[list, list]:
|
|
42
|
+
"""Lint a candidate chain against a forged language's ratified grammar."""
|
|
43
|
+
with connect(language.db) as cx:
|
|
44
|
+
return _gate(cx, candidate, scope=language.scope)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def grammar(language: Language) -> list[str]:
|
|
48
|
+
"""The ratified grammar lines of a forged language."""
|
|
49
|
+
with connect(language.db) as cx:
|
|
50
|
+
return grammar_lines(list_rules(cx, "adopted", scope=language.scope))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def package_skill(name: str, body: str, *, out_dir: str, description: str,
|
|
54
|
+
extra: dict | None = None):
|
|
55
|
+
"""Wrap a compiled chain body as a publishable `<name>/SKILL.md` package."""
|
|
56
|
+
return write_skill(name, description, body, out_dir=out_dir, extra=extra)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
__all__ = ["Language", "forge", "gate_language", "grammar", "package_skill"]
|
chaincompiler/persona.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Persona compiler — the front-end that ingests a glyph-persona-program and emits
|
|
2
|
+
the artifacts the rest of ChainCompiler already eats.
|
|
3
|
+
|
|
4
|
+
A BizziBee-style prompt is not prose: it is a program in a cognition-DSL with three
|
|
5
|
+
layers, each of which a ChainCompiler tool already compiles —
|
|
6
|
+
|
|
7
|
+
[VarDefs]{ [🌸💧]=NectarWF, 📃=drilldown, … } → a glyphsteer LEGEND (glyph↔meaning)
|
|
8
|
+
🌸💧 → 🍯 → 🍹 (dense-rune chains) → HoneyC compiles / rulecatcher gates
|
|
9
|
+
⚙️0–5 (if / while / for / 🔁 / terminal) → a workflow (the SI executes; here: extracted)
|
|
10
|
+
[ROLE]…[/ROLE] (the persona wrapper) → a SKILL.md (the one type)
|
|
11
|
+
|
|
12
|
+
So this module parses the human-authored glyph-persona into: a `legend.json`, a list of
|
|
13
|
+
workflow steps, and a `<cogid>/SKILL.md` — putting the persona INSIDE the closed algebra.
|
|
14
|
+
Full execution of the ⚙️ control flow is the SI's job (ASPIRATIONAL: `persona run`).
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import re
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
from .skillpack import slugify, write_skill
|
|
23
|
+
|
|
24
|
+
# operator glyphs that are NOT vocabulary entries (arrows / connectors)
|
|
25
|
+
_OPERATORS = set("→⇒⇔↔⟶⇄⟷=+/")
|
|
26
|
+
_NONASCII = re.compile(r"[^\x00-\x7f]+")
|
|
27
|
+
_IDENT = re.compile(r"[A-Za-z][A-Za-z0-9]*")
|
|
28
|
+
_HEADER = re.compile(r"^\[([A-Za-z][A-Za-z0-9]*)\]:\s*(.*)$", re.M)
|
|
29
|
+
_VARDEFS = re.compile(r"\[VarDefs\]:\s*\{(.*?)\}\s*(?:\n|$)", re.S)
|
|
30
|
+
_STEP = re.compile(r"⚙️([0-9][0-9.]*)\)\s*`?(.*)")
|
|
31
|
+
_CTRL = re.compile(r"\b(if|while|for|end)\b|🔁", re.I)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class Persona:
|
|
36
|
+
name: str
|
|
37
|
+
description: str
|
|
38
|
+
fields: dict[str, str] = field(default_factory=dict)
|
|
39
|
+
legend: object = None # a glyphsteer.Vocabulary
|
|
40
|
+
steps: list[dict] = field(default_factory=list)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# ---- block parsing ----------------------------------------------------------
|
|
44
|
+
def parse_header(text: str) -> dict[str, str]:
|
|
45
|
+
"""The `[TAG]: value` header fields (ROLE, CogID, LAW, Mission, …)."""
|
|
46
|
+
return {k: v.strip() for k, v in _HEADER.findall(text)}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def vardefs_text(text: str) -> str:
|
|
50
|
+
m = _VARDEFS.search(text)
|
|
51
|
+
return m.group(1) if m else ""
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# ---- VarDefs → legend -------------------------------------------------------
|
|
55
|
+
def _clean_glyph(run: str) -> str:
|
|
56
|
+
return "".join(ch for ch in run if ch not in _OPERATORS).strip()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def extract_legend(text: str):
|
|
60
|
+
"""Parse the VarDefs glyph↔name pairs into a glyphsteer Vocabulary (best-effort)."""
|
|
61
|
+
from glyphsteer import Axis, Vocabulary, author
|
|
62
|
+
raw = vardefs_text(text) or text
|
|
63
|
+
specs, gseen, nseen = [], set(), set()
|
|
64
|
+
for piece in re.split(r"[,\n]", raw):
|
|
65
|
+
glyph_runs = [g for g in (_clean_glyph(r) for r in _NONASCII.findall(piece)) if g]
|
|
66
|
+
names = _IDENT.findall(piece)
|
|
67
|
+
if not glyph_runs or not names:
|
|
68
|
+
continue
|
|
69
|
+
glyph, name = glyph_runs[0], names[0]
|
|
70
|
+
if glyph in gseen or name in nseen:
|
|
71
|
+
continue
|
|
72
|
+
try:
|
|
73
|
+
Vocabulary([Axis(name, glyph)]) # validates clean glyph + derivable tag
|
|
74
|
+
except ValueError:
|
|
75
|
+
continue
|
|
76
|
+
gseen.add(glyph); nseen.add(name)
|
|
77
|
+
specs.append({"name": name, "glyph": glyph, "description": piece.strip()})
|
|
78
|
+
return author(specs)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# ---- ⚙️ steps → workflow ----------------------------------------------------
|
|
82
|
+
def extract_workflow(text: str) -> list[dict]:
|
|
83
|
+
"""The numbered ⚙️N) steps, in order, with detected control-flow keywords."""
|
|
84
|
+
steps = []
|
|
85
|
+
for num, body in _STEP.findall(text):
|
|
86
|
+
body = body.strip().rstrip("`").strip()
|
|
87
|
+
ctrl = sorted({m.group(0).lower() for m in _CTRL.finditer(body)})
|
|
88
|
+
steps.append({"step": num, "ctrl": ctrl, "body": body[:140]})
|
|
89
|
+
return steps
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# ---- compile ----------------------------------------------------------------
|
|
93
|
+
def parse_persona(text: str) -> Persona:
|
|
94
|
+
h = parse_header(text)
|
|
95
|
+
name = h.get("CogID") or h.get("ROLE") or "persona"
|
|
96
|
+
name = re.sub(r"[*]+$", "", name).strip()
|
|
97
|
+
return Persona(
|
|
98
|
+
name=name,
|
|
99
|
+
description=h.get("Mission", f"{name} persona"),
|
|
100
|
+
fields=h,
|
|
101
|
+
legend=extract_legend(text),
|
|
102
|
+
steps=extract_workflow(text),
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _render_body(p: Persona) -> str:
|
|
107
|
+
from glyphsteer import render_legend
|
|
108
|
+
h = p.fields
|
|
109
|
+
out = [f"# {h.get('ROLE', p.name)} — compiled persona", ""]
|
|
110
|
+
for key in ("LAW", "Mission", "FnMx", "ActsLike", "OutputWrapper"):
|
|
111
|
+
if h.get(key):
|
|
112
|
+
out.append(f"- **{key}**: {h[key]}")
|
|
113
|
+
out += ["", "## Legend (the glyph vocabulary)", "```", render_legend(p.legend), "```", ""]
|
|
114
|
+
out += ["## Workflow (⚙️ steps)", ""]
|
|
115
|
+
for s in p.steps:
|
|
116
|
+
ctrl = f" _[{', '.join(s['ctrl'])}]_" if s["ctrl"] else ""
|
|
117
|
+
out.append(f"{s['step']}. {s['body']}{ctrl}")
|
|
118
|
+
out += ["", "> Terminal output is reached only after a multi-round sequence of the "
|
|
119
|
+
"looping steps (the ⚙️ workflow is executable via the SI — ASPIRATIONAL)."]
|
|
120
|
+
return "\n".join(out)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def lint_pipeline(p: Persona) -> dict | None:
|
|
124
|
+
"""If the legend + ChainCompiler grammar gate are available, lint a glyph chain
|
|
125
|
+
drawn from the legend (rulecatcher syntax gate). Returns a verdict or None."""
|
|
126
|
+
try:
|
|
127
|
+
from glyphsteer import GlyphGrammar
|
|
128
|
+
except Exception:
|
|
129
|
+
return None
|
|
130
|
+
glyphs = p.legend.glyphs
|
|
131
|
+
if len(glyphs) < 2:
|
|
132
|
+
return None
|
|
133
|
+
code = p.legend.code(glyphs[:3])
|
|
134
|
+
try:
|
|
135
|
+
with GlyphGrammar(p.legend, scope=f"persona_{slugify(p.name)}") as gg:
|
|
136
|
+
lint = gg.lint(code)
|
|
137
|
+
return {"chain": code, "verdict": lint.verdict}
|
|
138
|
+
except Exception:
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def compile_persona(text: str, out_dir: str | Path) -> dict:
|
|
143
|
+
"""Compile a glyph-persona-program → `<cogid>/SKILL.md` + `legend.json`."""
|
|
144
|
+
from glyphsteer import save_legend
|
|
145
|
+
p = parse_persona(text)
|
|
146
|
+
skill_path = write_skill(p.name, p.description, _render_body(p), out_dir=out_dir,
|
|
147
|
+
extra={"glyphs": p.legend.code(p.legend.glyphs[:1]) or ""})
|
|
148
|
+
legend_path = skill_path.parent / "legend.json"
|
|
149
|
+
save_legend(p.legend, legend_path)
|
|
150
|
+
return {
|
|
151
|
+
"name": p.name,
|
|
152
|
+
"skill": str(skill_path),
|
|
153
|
+
"legend": str(legend_path),
|
|
154
|
+
"axes": len(p.legend.axes),
|
|
155
|
+
"steps": len(p.steps),
|
|
156
|
+
"gate": lint_pipeline(p),
|
|
157
|
+
}
|
chaincompiler/prime.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Build the re-injectable PRIME block — the output that closes the loop.
|
|
2
|
+
|
|
3
|
+
A prime is a context block that (a) tells the LLM the ratified grammar of the
|
|
4
|
+
notation so it generates in-shape, and (b) shows a compiled example so it knows
|
|
5
|
+
what the notation MEANS. Re-injecting the prime self-primes the model; every
|
|
6
|
+
chain it then emits is gated by the same grammar (bridge.gate).
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from .bridge import compile_chain, grammar_lines
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def build_prime(scope: str, adopted_rows: list, example_chain: str) -> str:
|
|
14
|
+
compiled = compile_chain(example_chain)
|
|
15
|
+
g = grammar_lines(adopted_rows)
|
|
16
|
+
|
|
17
|
+
sections = [
|
|
18
|
+
f'# PRIME — "{scope}" cognition-chain notation',
|
|
19
|
+
"",
|
|
20
|
+
"You think in this notation. Write cognition chains in the shape below; "
|
|
21
|
+
"every chain you emit is gated against the grammar (fix violations before continuing).",
|
|
22
|
+
"",
|
|
23
|
+
f"## Ratified grammar ({len(g)} rules, learned from examples)",
|
|
24
|
+
*(g or ["(none ratified yet)"]),
|
|
25
|
+
"",
|
|
26
|
+
"## A compiled chain (what one MEANS)",
|
|
27
|
+
f"chain: {example_chain.strip()}",
|
|
28
|
+
f"readable: {compiled['readable']}",
|
|
29
|
+
"",
|
|
30
|
+
"triples:",
|
|
31
|
+
*(f" {line}" for line in compiled["triples"].splitlines()),
|
|
32
|
+
]
|
|
33
|
+
if compiled["prose"].strip():
|
|
34
|
+
sections += ["", "prose:", f" {compiled['prose']}"]
|
|
35
|
+
sections += [
|
|
36
|
+
"",
|
|
37
|
+
"## Directive",
|
|
38
|
+
"Emit chains of this form. End a reasoning chain with a bounded |Predict| "
|
|
39
|
+
"(the kill-criterion). Stay inside the grammar; the gate will reject drift.",
|
|
40
|
+
]
|
|
41
|
+
return "\n".join(sections)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""chaincompiler.skillpack — the skill-packager, now living in the BASE.
|
|
2
|
+
|
|
3
|
+
MOVED DOWN to `prompt_engineering.skillpack` (REBUILD-SPEC.md §7 — single source of truth, D1). This
|
|
4
|
+
module now just re-exports it, so `from chaincompiler.skillpack import write_skill` and
|
|
5
|
+
`from chaincompiler import write_skill, slugify, skill_markdown` stay byte-stable for existing consumers
|
|
6
|
+
(archetype, the *CC tests).
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from prompt_engineering.skillpack import slugify, skill_markdown, write_skill
|
|
11
|
+
|
|
12
|
+
__all__ = ["slugify", "skill_markdown", "write_skill"]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chaincompiler
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: The printing press for agent cognition chains: learn → gate → compile → prime
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: honeyc==0.3.0
|
|
7
|
+
Requires-Dist: rulecatcher==0.3.0
|
|
8
|
+
Requires-Dist: agent-skilltree>=0.4.0
|
|
9
|
+
Requires-Dist: agent-prompt-engineering>=0.2.0
|
|
10
|
+
Provides-Extra: persona
|
|
11
|
+
Requires-Dist: glyphsteer==0.3.0; extra == "persona"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
chaincompiler/__init__.py,sha256=R8JOQ24tFq7VExtGIgocDKHiy5gN7OYHSkUsA1qB-y4,1681
|
|
2
|
+
chaincompiler/bridge.py,sha256=uc75cN4IurAiq5Ec0o6Y_pLitmmoyybEeTdFkUS23kk,1294
|
|
3
|
+
chaincompiler/forge.py,sha256=kSOHwGgYexrY2vJqzhBz56XkaSZDuzQElF-PYMRx-6o,2486
|
|
4
|
+
chaincompiler/persona.py,sha256=2ZGI4zcAUuKYBY0DOdWHesU2oTuBeDaww4d2KTyXGno,6342
|
|
5
|
+
chaincompiler/prime.py,sha256=jqpN1mHO9cp_0iLDnNK7ynBy2OEtD755pTRqJJbv4so,1630
|
|
6
|
+
chaincompiler/skillpack.py,sha256=SEjy1XqXeDYUP-tSE0ObNhuQ9I1qGbtToFgSdOy9Oj4,575
|
|
7
|
+
chaincompiler-0.3.0.dist-info/METADATA,sha256=rzMK5NySvCUiXXCKEe2kHhRyGmVooG8KT8KCU0_XVjc,399
|
|
8
|
+
chaincompiler-0.3.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
9
|
+
chaincompiler-0.3.0.dist-info/top_level.txt,sha256=YqHPev5jmDAlZqEahcPBrvKEv02NYNUjUFacgVw-DSM,14
|
|
10
|
+
chaincompiler-0.3.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
chaincompiler
|