chaincompiler-accc 0.3.0__tar.gz
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_accc-0.3.0/PKG-INFO +9 -0
- chaincompiler_accc-0.3.0/README.md +68 -0
- chaincompiler_accc-0.3.0/pyproject.toml +16 -0
- chaincompiler_accc-0.3.0/setup.cfg +4 -0
- chaincompiler_accc-0.3.0/src/accc/__init__.py +15 -0
- chaincompiler_accc-0.3.0/src/accc/cli.py +76 -0
- chaincompiler_accc-0.3.0/src/accc/forge.py +87 -0
- chaincompiler_accc-0.3.0/src/accc/notation.py +45 -0
- chaincompiler_accc-0.3.0/src/accc/render.py +44 -0
- chaincompiler_accc-0.3.0/src/chaincompiler_accc.egg-info/PKG-INFO +9 -0
- chaincompiler_accc-0.3.0/src/chaincompiler_accc.egg-info/SOURCES.txt +14 -0
- chaincompiler_accc-0.3.0/src/chaincompiler_accc.egg-info/dependency_links.txt +1 -0
- chaincompiler_accc-0.3.0/src/chaincompiler_accc.egg-info/entry_points.txt +2 -0
- chaincompiler_accc-0.3.0/src/chaincompiler_accc.egg-info/requires.txt +4 -0
- chaincompiler_accc-0.3.0/src/chaincompiler_accc.egg-info/top_level.txt +1 -0
- chaincompiler_accc-0.3.0/tests/test_accc.py +63 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chaincompiler-accc
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Attention-Chain Compiler-Compiler — the atom of the cognition-chain stack
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: chaincompiler==0.3.0
|
|
7
|
+
Requires-Dist: honeyc==0.3.0
|
|
8
|
+
Requires-Dist: rulecatcher==0.3.0
|
|
9
|
+
Requires-Dist: click
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# ACCC — Attention-Chain Compiler-Compiler
|
|
2
|
+
|
|
3
|
+
The **atom** of the cognition-chain stack: `ACCC → CORCC → SCCC`.
|
|
4
|
+
|
|
5
|
+
An **attention chain (AC)** is **inner** — not necessarily spoken. The model uses
|
|
6
|
+
it as a *template for a section* of its output, or as a *thinking scaffold*: a
|
|
7
|
+
silent sequence of attention foci converging on a held focus. (Contrast CORCC's
|
|
8
|
+
CoR, which is the **outer** paragraph the model must *say* and is gauged for
|
|
9
|
+
persona-melt.) Written in Dense Rune-Chain so HoneyC compiles it and rulecatcher
|
|
10
|
+
catches its grammar:
|
|
11
|
+
|
|
12
|
+
```txt
|
|
13
|
+
[Focus_1] ⇒ [Focus_2] ⇒ ... ⇒ |Held|
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
ACCC is a **compiler-compiler**, not a compiler: `forge()` mints a *new* AC
|
|
17
|
+
language for a task/domain (it doesn't just compile one chain). Each forged
|
|
18
|
+
language is a rulecatcher scope holding the ratified grammar; `gate()` enforces
|
|
19
|
+
it; `prime()` emits the re-injectable block.
|
|
20
|
+
|
|
21
|
+
## The stack it sits in
|
|
22
|
+
|
|
23
|
+
| layer | chain of… | each node expands to… | built |
|
|
24
|
+
|------|-----------|-----------------------|-------|
|
|
25
|
+
| **ACCC** | attention foci | — (the atom) | ✅ |
|
|
26
|
+
| CORCC | reasoning steps | a forged **AC** | next |
|
|
27
|
+
| SCCC | skills | a **CoR** (+ can forge new languages) | after |
|
|
28
|
+
|
|
29
|
+
Composition is HoneyC scope/drilldown: a CoR step `[Frame]:{ <ac> }` *contains*
|
|
30
|
+
the attention chain that powers it.
|
|
31
|
+
|
|
32
|
+
## Built on
|
|
33
|
+
|
|
34
|
+
- **rulecatcher** — catches + gates the emergent grammar (`learn`, `lint`, the
|
|
35
|
+
`orthogonal`/`syntax_break` verdict).
|
|
36
|
+
- **HoneyC** — compiles the Dense Rune-Chain notation.
|
|
37
|
+
- **chaincompiler** — the generic `learn → gate → compile → prime` loop. ACCC is
|
|
38
|
+
the first domain layer on it.
|
|
39
|
+
|
|
40
|
+
## Run
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install --no-build-isolation --no-deps -e . # rulecatcher/honeyc/chaincompiler already installed
|
|
44
|
+
accc demo # forge 2 AC languages, gate, prime
|
|
45
|
+
accc forge debug examples/debug.ac --strict # mint a domain AC language
|
|
46
|
+
pytest # 5 tests
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## What the demo shows
|
|
50
|
+
|
|
51
|
+
1. **forge** `generic` (shape-only) and `debug` (strict, vocabulary-pinned) — two
|
|
52
|
+
distinct attention-chain languages, induced from examples.
|
|
53
|
+
2. **prime** the debug language → grammar + a compiled attention block.
|
|
54
|
+
3. **gate** a valid debug AC → `clean ✓`.
|
|
55
|
+
4. **gate** an off-domain chain (`[Goal] ⇒ …` in the debug language) → rejected
|
|
56
|
+
with verdict **`orthogonal`** (valid identifier, wrong vocabulary → steerable),
|
|
57
|
+
fix: insert `Symptom`.
|
|
58
|
+
|
|
59
|
+
## API (what CORCC will consume)
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from accc import forge, gate, prime, attention_block, parse_ac
|
|
63
|
+
|
|
64
|
+
lang = forge("debug", debug_examples, db=".accc.db", strict=True)
|
|
65
|
+
violations, fixes = gate(lang, "[Symptom] ⇒ [Repro] ⇒ |Localize|")
|
|
66
|
+
block = attention_block("debug", "[Symptom] ⇒ [Repro] ⇒ |Localize|")
|
|
67
|
+
foci, held = parse_ac("[Symptom] ⇒ [Repro] ⇒ |Localize|")
|
|
68
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "chaincompiler-accc"
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Attention-Chain Compiler-Compiler — the atom of the cognition-chain stack"
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
dependencies = ["chaincompiler==0.3.0", "honeyc==0.3.0", "rulecatcher==0.3.0", "click"]
|
|
11
|
+
|
|
12
|
+
[project.scripts]
|
|
13
|
+
accc = "accc.cli:main"
|
|
14
|
+
|
|
15
|
+
[tool.setuptools.packages.find]
|
|
16
|
+
where = ["src"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""ACCC — Attention-Chain Compiler-Compiler. The atom of the cognition stack.
|
|
2
|
+
|
|
3
|
+
ACCC → CORCC → SCCC: a CoR step embeds a forged AC; a skill embeds a CoR.
|
|
4
|
+
"""
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
__version__ = "0.3.0"
|
|
8
|
+
|
|
9
|
+
from .forge import Language, forge, gate, grammar, package, prime
|
|
10
|
+
from .render import attention_block, parse_ac
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"forge", "gate", "grammar", "prime", "package", "Language",
|
|
14
|
+
"attention_block", "parse_ac", "__version__",
|
|
15
|
+
]
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""accc — forge attention-chain languages, gate them, compile them to blocks."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import tempfile
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
from .forge import forge, gate, grammar, prime
|
|
10
|
+
from .notation import SEED_LANGUAGES
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.group()
|
|
14
|
+
@click.version_option(message="accc %(version)s")
|
|
15
|
+
def main() -> None:
|
|
16
|
+
"""Attention-Chain Compiler-Compiler."""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@main.command()
|
|
20
|
+
@click.argument("name")
|
|
21
|
+
@click.argument("examples_file", type=click.Path(exists=True, dir_okay=False, path_type=Path))
|
|
22
|
+
@click.option("--db", default=".accc.db")
|
|
23
|
+
@click.option("--strict/--shape-only", default=False, help="Pin focus vocabulary (strict) or shape only.")
|
|
24
|
+
def forge_cmd(name: str, examples_file: Path, db: str, strict: bool) -> None:
|
|
25
|
+
"""Forge an AC language NAME from EXAMPLES_FILE (one chain per line)."""
|
|
26
|
+
examples = [ln for ln in examples_file.read_text(encoding="utf-8").splitlines() if ln.strip()]
|
|
27
|
+
lang = forge(name, examples, db=db, strict=strict)
|
|
28
|
+
click.echo(f"forged '{lang.name}' (scope {lang.scope}, {lang.rule_count} rules):")
|
|
29
|
+
for line in grammar(lang):
|
|
30
|
+
click.echo(" " + line)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
main.add_command(forge_cmd, name="forge")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@main.command()
|
|
37
|
+
def demo() -> None:
|
|
38
|
+
"""Forge two distinct AC languages, gate them, and emit a prime block."""
|
|
39
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
40
|
+
db = str(Path(tmp) / "accc.db")
|
|
41
|
+
|
|
42
|
+
click.echo("══ 1. FORGE — mint a generic AC language (shape only) ══")
|
|
43
|
+
generic = forge("generic", SEED_LANGUAGES["generic"], db=db)
|
|
44
|
+
for line in grammar(generic):
|
|
45
|
+
click.echo(" " + line)
|
|
46
|
+
|
|
47
|
+
click.echo("\n══ 2. FORGE — mint a DEBUG AC language (strict: pins the vocabulary) ══")
|
|
48
|
+
debug = forge("debug", SEED_LANGUAGES["debug"], db=db, strict=True)
|
|
49
|
+
click.echo(f" debug language scope={debug.scope}, {debug.rule_count} rules "
|
|
50
|
+
"(distinct from generic — domain-specific attention)")
|
|
51
|
+
|
|
52
|
+
click.echo("\n══ 3. PRIME — the re-injectable attention block for the debug language ══")
|
|
53
|
+
click.echo(prime(debug, "[Symptom] ⇒ [Logs] ⇒ [Hypothesis] ⇒ |Localize|"))
|
|
54
|
+
|
|
55
|
+
click.echo("\n══ 4. GATE — a valid debug AC (should pass) ══")
|
|
56
|
+
good = "[Symptom] ⇒ [Repro] ⇒ [Diff] ⇒ |Localize|"
|
|
57
|
+
v, _ = gate(debug, good)
|
|
58
|
+
click.echo(f" {good}\n → {'clean ✓' if not v else 'REJECTED'}")
|
|
59
|
+
|
|
60
|
+
click.echo("\n══ 5. GATE — an off-domain AC (planning foci in the debug language) ══")
|
|
61
|
+
wrong = "[Goal] ⇒ [Constraints] ⇒ [Evidence] ⇒ |Plan|"
|
|
62
|
+
v, fixes = gate(debug, wrong)
|
|
63
|
+
if v:
|
|
64
|
+
vio, fx = v[0], fixes[0]
|
|
65
|
+
click.echo(f" {wrong}\n ✗ {vio.verdict}: expected {vio.expected_token!r}, "
|
|
66
|
+
f"found {vio.found_token!r}; fix: {list(fx.candidate_tokens) or fx.reason}")
|
|
67
|
+
else:
|
|
68
|
+
click.echo(" (clean — shape matched; strict vocab not violated)")
|
|
69
|
+
|
|
70
|
+
click.echo("\n══ 6. The CC point ══")
|
|
71
|
+
click.echo(" Two attention-chain LANGUAGES were minted from examples — not hand-written. "
|
|
72
|
+
"CORCC will embed a forged AC inside each reasoning step.")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
main()
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""ACCC — the Attention-Chain Compiler-Compiler. Made FROM ChainCompiler (DESIGN.md §2: ACCC imports CC).
|
|
2
|
+
|
|
3
|
+
The compiler-compiler move: `forge` mints a *new* AC language for a task/domain (it doesn't just compile
|
|
4
|
+
one chain). The generic machinery (forge a rulecatcher scope, gate against it, read the grammar, wrap a
|
|
5
|
+
body as SKILL.md) lives in `chaincompiler.forge`; ACCC specializes it to attention chains (the `ac:` kind
|
|
6
|
+
+ the attention-block render). CORCC consumes these: a reasoning step embeds a forged AC.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
# made FROM CC — the generic forge core (CC re-exports APE's write_skill/learn/gate underneath):
|
|
11
|
+
from chaincompiler import (
|
|
12
|
+
Language,
|
|
13
|
+
forge as _forge,
|
|
14
|
+
gate_language as _gate,
|
|
15
|
+
grammar as _grammar,
|
|
16
|
+
package_skill as _package,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from .render import attention_block, parse_ac
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def forge(name: str, examples: list[str], *, db: str, strict: bool = False) -> Language:
|
|
23
|
+
"""Mint an AC language for `name` from example chains (CC's forge, `ac:` kind).
|
|
24
|
+
|
|
25
|
+
strict=False → learn the SHAPE only (next_kind): any focus vocabulary is allowed.
|
|
26
|
+
strict=True → also pin the focus vocabulary (next_token): the gate enforces
|
|
27
|
+
domain-specific foci (e.g. a debug AC must open on a Symptom).
|
|
28
|
+
"""
|
|
29
|
+
return _forge("ac", name, examples, db=db, strict=strict)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def gate(language: Language, ac: str) -> tuple[list, list]:
|
|
33
|
+
"""Lint a candidate attention chain against a forged language."""
|
|
34
|
+
return _gate(language, ac)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def grammar(language: Language) -> list[str]:
|
|
38
|
+
return _grammar(language)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def package(name: str, ac: str, *, out_dir: str, description: str | None = None):
|
|
42
|
+
"""Compile an attention chain to a publishable `<name>/SKILL.md` package.
|
|
43
|
+
|
|
44
|
+
The body is a markdown file carrying the AC in its custom syntax + how to use
|
|
45
|
+
it. The dir/SKILL.md wrapper is just so any agent auto-loads it.
|
|
46
|
+
"""
|
|
47
|
+
foci, held = parse_ac(ac)
|
|
48
|
+
# NOTE: no ": " in the default — write_skill (APE) does not YAML-escape the
|
|
49
|
+
# description, and a plain scalar containing ": " emits unparseable frontmatter.
|
|
50
|
+
desc = description or (
|
|
51
|
+
f"Attention template (how to think) — attend to {', '.join(foci)}"
|
|
52
|
+
+ (f" → hold {held}" if held else "") + "."
|
|
53
|
+
)
|
|
54
|
+
body = "\n".join([
|
|
55
|
+
"This is an **attention chain** — an INNER template for how to think about something "
|
|
56
|
+
"(a scaffold for a section or for your thinking). Not necessarily spoken.",
|
|
57
|
+
"",
|
|
58
|
+
"## Chain (custom syntax)",
|
|
59
|
+
"```rune",
|
|
60
|
+
ac.strip(),
|
|
61
|
+
"```",
|
|
62
|
+
"",
|
|
63
|
+
"## How to use it",
|
|
64
|
+
attention_block(name, ac),
|
|
65
|
+
])
|
|
66
|
+
return _package(name, body, out_dir=out_dir, description=desc, extra={"kind": "attention-chain"})
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def prime(language: Language, exemplar: str) -> str:
|
|
70
|
+
"""The re-injectable PRIME for a forged AC language."""
|
|
71
|
+
g = grammar(language)
|
|
72
|
+
block = attention_block(language.name, exemplar)
|
|
73
|
+
return "\n".join([
|
|
74
|
+
f'# PRIME — attention-chain language "{language.name}"',
|
|
75
|
+
"",
|
|
76
|
+
"Direct your attention using chains of this shape. Every chain you emit is "
|
|
77
|
+
"gated against the language; fix violations before continuing.",
|
|
78
|
+
"",
|
|
79
|
+
f"## Ratified grammar ({len(g)} rules)",
|
|
80
|
+
*(g or ["(none)"]),
|
|
81
|
+
"",
|
|
82
|
+
"## Exemplar (compiled to an attention block)",
|
|
83
|
+
block,
|
|
84
|
+
"",
|
|
85
|
+
"## Directive",
|
|
86
|
+
"Emit attention chains in this language. End on a bounded |Held| focus.",
|
|
87
|
+
])
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""The Attention-Chain notation + seed corpora.
|
|
2
|
+
|
|
3
|
+
An ATTENTION CHAIN (AC) is the atom of the cognition stack: a prompt block that
|
|
4
|
+
sequences attention foci and converges on a held focus. It is what powers ONE
|
|
5
|
+
reasoning step (a CoR step embeds an AC). Written in Dense Rune-Chain so HoneyC
|
|
6
|
+
compiles it and rulecatcher catches its grammar:
|
|
7
|
+
|
|
8
|
+
[Focus_1] ⇒ [Focus_2] ⇒ ... ⇒ |Held|
|
|
9
|
+
|
|
10
|
+
- each [Focus_i] is something to attend to, in order
|
|
11
|
+
- ⇒ flows attention forward
|
|
12
|
+
- |Held| (bounded) is the convergence point attention is stabilized on
|
|
13
|
+
|
|
14
|
+
Different domains forge different AC languages: the SHAPE is shared, the focus
|
|
15
|
+
vocabulary and the held target differ. That is what makes ACCC a
|
|
16
|
+
compiler-compiler — it mints AC *languages*, not just compiles one AC.
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
# Generic planning attention chain: orient → converge on a plan.
|
|
21
|
+
GENERIC_AC = [
|
|
22
|
+
"[Goal] ⇒ [Constraints] ⇒ [Evidence] ⇒ |Plan|",
|
|
23
|
+
"[Goal] ⇒ [Risks] ⇒ [Evidence] ⇒ |Plan|",
|
|
24
|
+
"[Goal] ⇒ [Constraints] ⇒ [Options] ⇒ |Plan|",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
# Domain-specific AC: debugging. Different vocabulary, different held target.
|
|
28
|
+
DEBUG_AC = [
|
|
29
|
+
"[Symptom] ⇒ [Repro] ⇒ [Hypothesis] ⇒ |Localize|",
|
|
30
|
+
"[Symptom] ⇒ [Logs] ⇒ [Hypothesis] ⇒ |Localize|",
|
|
31
|
+
"[Symptom] ⇒ [Repro] ⇒ [Diff] ⇒ |Localize|",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
# Another domain: literature research.
|
|
35
|
+
RESEARCH_AC = [
|
|
36
|
+
"[Question] ⇒ [Sources] ⇒ [Claims] ⇒ |Synthesis|",
|
|
37
|
+
"[Question] ⇒ [Sources] ⇒ [Conflicts] ⇒ |Synthesis|",
|
|
38
|
+
"[Question] ⇒ [Gaps] ⇒ [Claims] ⇒ |Synthesis|",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
SEED_LANGUAGES = {
|
|
42
|
+
"generic": GENERIC_AC,
|
|
43
|
+
"debug": DEBUG_AC,
|
|
44
|
+
"research": RESEARCH_AC,
|
|
45
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Compile an attention chain into a usable attention-directing prompt block.
|
|
2
|
+
|
|
3
|
+
This is the AC-specific lens (HoneyC gives generic triples/prose; this turns an
|
|
4
|
+
AC into the actual block you inject to direct a model's attention).
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from honeyc.ast_nodes import Bounded, Chain, Entity, Glyph, Symbol, TypeAnn
|
|
9
|
+
from honeyc.parser import parse_text
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _label(term: object) -> str:
|
|
13
|
+
if isinstance(term, Bounded):
|
|
14
|
+
return _label(term.term)
|
|
15
|
+
if isinstance(term, TypeAnn):
|
|
16
|
+
return _label(term.term)
|
|
17
|
+
if isinstance(term, Entity):
|
|
18
|
+
return term.id
|
|
19
|
+
if isinstance(term, Symbol):
|
|
20
|
+
return term.name
|
|
21
|
+
if isinstance(term, Glyph):
|
|
22
|
+
return term.name or term.id
|
|
23
|
+
return str(term)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def parse_ac(ac: str) -> tuple[list[str], str | None]:
|
|
27
|
+
"""Return (ordered foci, held focus) for an attention chain."""
|
|
28
|
+
program = parse_text(ac)
|
|
29
|
+
chain = next((s for s in program.statements if isinstance(s, Chain)), None)
|
|
30
|
+
if chain is None:
|
|
31
|
+
raise ValueError(f"not an attention chain: {ac!r}")
|
|
32
|
+
foci = [_label(t) for t in chain.terms if not isinstance(t, Bounded)]
|
|
33
|
+
held_term = next((t for t in chain.terms if isinstance(t, Bounded)), None)
|
|
34
|
+
return foci, (_label(held_term) if held_term is not None else None)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def attention_block(name: str, ac: str) -> str:
|
|
38
|
+
"""The injectable prompt block that directs attention along the chain."""
|
|
39
|
+
foci, held = parse_ac(ac)
|
|
40
|
+
lines = [f"# Attention chain — {name}", "Attend, in order:"]
|
|
41
|
+
lines += [f" {i}. {focus}" for i, focus in enumerate(foci, 1)]
|
|
42
|
+
if held:
|
|
43
|
+
lines.append(f"Hold: {held} ← converge attention here, then act")
|
|
44
|
+
return "\n".join(lines)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chaincompiler-accc
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Attention-Chain Compiler-Compiler — the atom of the cognition-chain stack
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: chaincompiler==0.3.0
|
|
7
|
+
Requires-Dist: honeyc==0.3.0
|
|
8
|
+
Requires-Dist: rulecatcher==0.3.0
|
|
9
|
+
Requires-Dist: click
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/accc/__init__.py
|
|
4
|
+
src/accc/cli.py
|
|
5
|
+
src/accc/forge.py
|
|
6
|
+
src/accc/notation.py
|
|
7
|
+
src/accc/render.py
|
|
8
|
+
src/chaincompiler_accc.egg-info/PKG-INFO
|
|
9
|
+
src/chaincompiler_accc.egg-info/SOURCES.txt
|
|
10
|
+
src/chaincompiler_accc.egg-info/dependency_links.txt
|
|
11
|
+
src/chaincompiler_accc.egg-info/entry_points.txt
|
|
12
|
+
src/chaincompiler_accc.egg-info/requires.txt
|
|
13
|
+
src/chaincompiler_accc.egg-info/top_level.txt
|
|
14
|
+
tests/test_accc.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
accc
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""ACCC tests: forging distinct languages, compiling, and gating."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from accc import attention_block, forge, gate, parse_ac
|
|
7
|
+
from accc.notation import DEBUG_AC, GENERIC_AC
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_parse_ac_extracts_foci_and_held():
|
|
11
|
+
foci, held = parse_ac("[Symptom] ⇒ [Repro] ⇒ [Hypothesis] ⇒ |Localize|")
|
|
12
|
+
assert foci == ["Symptom", "Repro", "Hypothesis"]
|
|
13
|
+
assert held == "Localize"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_attention_block_renders_ordered_foci():
|
|
17
|
+
block = attention_block("debug", "[Symptom] ⇒ [Repro] ⇒ |Localize|")
|
|
18
|
+
assert "1. Symptom" in block
|
|
19
|
+
assert "2. Repro" in block
|
|
20
|
+
assert "Hold: Localize" in block
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_forge_two_distinct_languages(tmp_path: Path):
|
|
24
|
+
db = str(tmp_path / "ac.db")
|
|
25
|
+
generic = forge("generic", GENERIC_AC, db=db)
|
|
26
|
+
debug = forge("debug", DEBUG_AC, db=db, strict=True)
|
|
27
|
+
assert generic.scope != debug.scope
|
|
28
|
+
assert generic.rule_count > 0 and debug.rule_count > 0
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_strict_debug_language_gates_off_domain_chain(tmp_path: Path):
|
|
32
|
+
db = str(tmp_path / "ac.db")
|
|
33
|
+
debug = forge("debug", DEBUG_AC, db=db, strict=True)
|
|
34
|
+
# valid debug chain passes
|
|
35
|
+
ok, _ = gate(debug, "[Symptom] ⇒ [Repro] ⇒ [Diff] ⇒ |Localize|")
|
|
36
|
+
assert ok == []
|
|
37
|
+
# off-domain planning chain is rejected by the pinned vocabulary
|
|
38
|
+
bad, _ = gate(debug, "[Goal] ⇒ [Constraints] ⇒ [Evidence] ⇒ |Plan|")
|
|
39
|
+
assert bad, "strict debug language should reject off-domain foci"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_shape_only_language_accepts_any_vocabulary(tmp_path: Path):
|
|
43
|
+
db = str(tmp_path / "ac.db")
|
|
44
|
+
generic = forge("generic", GENERIC_AC, db=db) # shape only
|
|
45
|
+
# a novel-vocabulary chain of the same SHAPE should pass
|
|
46
|
+
ok, _ = gate(generic, "[Aim] ⇒ [Limits] ⇒ [Facts] ⇒ |Sketch|")
|
|
47
|
+
assert ok == []
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_default_description_yields_parseable_frontmatter(tmp_path: Path):
|
|
51
|
+
"""Regression: write_skill (APE) does not YAML-escape descriptions, so a default
|
|
52
|
+
description containing ': ' emits unparseable SKILL.md frontmatter. The *CC
|
|
53
|
+
defaults must therefore be colon-free (2026-08-12; found minting real ACs)."""
|
|
54
|
+
import yaml
|
|
55
|
+
|
|
56
|
+
from accc import package
|
|
57
|
+
|
|
58
|
+
path = package("yamlcheck", "[Symptom] ⇒ [Repro] ⇒ |Localize|", out_dir=str(tmp_path))
|
|
59
|
+
front = path.read_text(encoding="utf-8").split("---")[1]
|
|
60
|
+
meta = yaml.safe_load(front) # raises on the ': ' defect
|
|
61
|
+
assert meta["name"] == "yamlcheck"
|
|
62
|
+
assert meta["kind"] == "attention-chain"
|
|
63
|
+
assert ": " not in meta["description"]
|