code-factory-2-forge 0.6.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.
- code_factory_2_forge-0.6.0.dist-info/METADATA +308 -0
- code_factory_2_forge-0.6.0.dist-info/RECORD +29 -0
- code_factory_2_forge-0.6.0.dist-info/WHEEL +5 -0
- code_factory_2_forge-0.6.0.dist-info/entry_points.txt +2 -0
- code_factory_2_forge-0.6.0.dist-info/licenses/LICENSE-APACHE +18 -0
- code_factory_2_forge-0.6.0.dist-info/licenses/LICENSE-MIT +21 -0
- code_factory_2_forge-0.6.0.dist-info/licenses/NOTICE +6 -0
- code_factory_2_forge-0.6.0.dist-info/top_level.txt +1 -0
- forgeline/__init__.py +14 -0
- forgeline/adapters.py +56 -0
- forgeline/attribution.py +71 -0
- forgeline/cli.py +101 -0
- forgeline/demo.py +83 -0
- forgeline/demo_learning.py +44 -0
- forgeline/gates/__init__.py +4 -0
- forgeline/gates/adversary.py +45 -0
- forgeline/gates/judge.py +26 -0
- forgeline/gates/qa_audit.py +134 -0
- forgeline/gates/reverse_classical.py +118 -0
- forgeline/gates/runtime_smoke.py +194 -0
- forgeline/gates/skill_check.py +14 -0
- forgeline/intent_thread.py +76 -0
- forgeline/learning.py +116 -0
- forgeline/orchestrator.py +263 -0
- forgeline/refinement.py +76 -0
- forgeline/run_store.py +43 -0
- forgeline/skill_memory.py +52 -0
- forgeline/ssat.py +93 -0
- forgeline/states.py +41 -0
forgeline/ssat.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Semantic Software Architecture Tree — architecture as code, not a doc.
|
|
2
|
+
|
|
3
|
+
An SSAT is a YAML contract: modules, their public signatures, allowed
|
|
4
|
+
dependency edges, and invariants. It is BOTH the scaffold source AND the
|
|
5
|
+
CI gate — the same artifact that generates the skeleton also detects
|
|
6
|
+
'structural erosion' when filled code violates the declared boundaries.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
import ast, re
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
import yaml
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class ArchViolation:
|
|
16
|
+
code: str
|
|
17
|
+
message: str
|
|
18
|
+
where: str = ""
|
|
19
|
+
|
|
20
|
+
def load_ssat(path: Path) -> dict:
|
|
21
|
+
return yaml.safe_load(Path(path).read_text())
|
|
22
|
+
|
|
23
|
+
def scaffold_from_ssat(ssat: dict, out_dir: Path) -> list[Path]:
|
|
24
|
+
"""Generate signature-only files with valid imports from the SSAT."""
|
|
25
|
+
out_dir = Path(out_dir); created = []
|
|
26
|
+
for mod in ssat.get("modules", []):
|
|
27
|
+
p = out_dir/mod["path"]
|
|
28
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
29
|
+
lines = ['"""AUTO-SCAFFOLD from SSAT. Fill bodies only; do not change signatures."""']
|
|
30
|
+
for imp in mod.get("imports", []):
|
|
31
|
+
lines.append(f"import {imp}" if "." not in imp else f"from {imp.rsplit('.',1)[0]} import {imp.rsplit('.',1)[1]}")
|
|
32
|
+
lines.append("")
|
|
33
|
+
for fn in mod.get("functions", []):
|
|
34
|
+
args = ", ".join(fn.get("args", []))
|
|
35
|
+
ret = fn.get("returns", "None")
|
|
36
|
+
lines.append(f"def {fn['name']}({args}) -> {ret}:")
|
|
37
|
+
lines.append(f' """{fn.get("doc","TODO")}"""')
|
|
38
|
+
lines.append(" raise NotImplementedError # FILL")
|
|
39
|
+
lines.append("")
|
|
40
|
+
p.write_text("\n".join(lines)); created.append(p)
|
|
41
|
+
return created
|
|
42
|
+
|
|
43
|
+
def _module_of(path: str, ssat: dict) -> str | None:
|
|
44
|
+
for mod in ssat.get("modules", []):
|
|
45
|
+
if path.endswith(mod["path"]):
|
|
46
|
+
return mod["name"]
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
def check_erosion(ssat: dict, src_dir: Path) -> list[ArchViolation]:
|
|
50
|
+
"""Architecture-as-CI-gate: detect signature drift + illegal dependency edges."""
|
|
51
|
+
src_dir = Path(src_dir); violations = []
|
|
52
|
+
allowed = {(e["from"], e["to"]) for e in ssat.get("dependencies", [])}
|
|
53
|
+
names = {m["name"]: m for m in ssat.get("modules", [])}
|
|
54
|
+
path_to_name = {m["path"]: m["name"] for m in ssat.get("modules", [])}
|
|
55
|
+
for mod in ssat.get("modules", []):
|
|
56
|
+
p = src_dir/mod["path"]
|
|
57
|
+
if not p.exists():
|
|
58
|
+
violations.append(ArchViolation("E_MISSING_MODULE", f"{mod['path']} declared in SSAT but absent"))
|
|
59
|
+
continue
|
|
60
|
+
try:
|
|
61
|
+
tree = ast.parse(p.read_text())
|
|
62
|
+
except SyntaxError as e:
|
|
63
|
+
violations.append(ArchViolation("E_SYNTAX", str(e), mod["path"])); continue
|
|
64
|
+
# signature drift
|
|
65
|
+
declared = {f["name"]: f for f in mod.get("functions", [])}
|
|
66
|
+
found = {n.name: n for n in ast.walk(tree) if isinstance(n, ast.FunctionDef)}
|
|
67
|
+
for fname, fspec in declared.items():
|
|
68
|
+
if fname not in found:
|
|
69
|
+
violations.append(ArchViolation("E_SIG_MISSING", f"{fname} declared but not implemented", mod["path"]))
|
|
70
|
+
continue
|
|
71
|
+
got_args = [a.arg for a in found[fname].args.args]
|
|
72
|
+
want_args = [a.split(":")[0].strip() for a in fspec.get("args", [])]
|
|
73
|
+
if got_args != want_args:
|
|
74
|
+
violations.append(ArchViolation("E_SIG_DRIFT",
|
|
75
|
+
f"{fname}({got_args}) != SSAT ({want_args})", mod["path"]))
|
|
76
|
+
# illegal dependency edges
|
|
77
|
+
this = mod["name"]
|
|
78
|
+
for node in ast.walk(tree):
|
|
79
|
+
if isinstance(node, (ast.Import, ast.ImportFrom)):
|
|
80
|
+
mods = [a.name for a in node.names] if isinstance(node, ast.Import) else [node.module or ""]
|
|
81
|
+
for m in mods:
|
|
82
|
+
target = names.get(m.split(".")[-1]) or names.get(m)
|
|
83
|
+
tname = target["name"] if target else None
|
|
84
|
+
if tname and tname != this and (this, tname) not in allowed:
|
|
85
|
+
violations.append(ArchViolation("E_ILLEGAL_DEP",
|
|
86
|
+
f"{this} -> {tname} not in SSAT dependency allowlist", mod["path"]))
|
|
87
|
+
for inv in ssat.get("invariants", []):
|
|
88
|
+
pat = inv["forbid_pattern"]
|
|
89
|
+
for mod in ssat.get("modules", []):
|
|
90
|
+
p = src_dir/mod["path"]
|
|
91
|
+
if p.exists() and re.search(pat, p.read_text()):
|
|
92
|
+
violations.append(ArchViolation("E_INVARIANT", f"{inv['name']}: forbidden pattern {pat!r}", mod["path"]))
|
|
93
|
+
return violations
|
forgeline/states.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""The Agentic SDLC state machine. States are explicit, transitions are
|
|
2
|
+
gated, and every transition is a receipt. Humans own confidence gates;
|
|
3
|
+
agents own execution between them."""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
from enum import Enum
|
|
6
|
+
|
|
7
|
+
class State(str, Enum):
|
|
8
|
+
INTENT = "intent" # vague human intent captured
|
|
9
|
+
EXPANDED = "expanded" # use cases drafted (human confidence gate)
|
|
10
|
+
ARCHITECTED = "architected" # SSAT / architecture-as-code produced
|
|
11
|
+
SCAFFOLDED = "scaffolded" # signatures + files, valid imports
|
|
12
|
+
FILLED = "filled" # function bodies implemented
|
|
13
|
+
REVIEWED = "reviewed" # judge + adversary passed
|
|
14
|
+
ARCH_GATED = "arch_gated" # architecture CI gate passed
|
|
15
|
+
TESTS_VERIFIED = "tests_verified" # smoke checks proven non-hollow
|
|
16
|
+
SMOKED = "smoked" # runtime behavior verified (smoke gate)
|
|
17
|
+
SHIPPED = "shipped"
|
|
18
|
+
BLOCKED = "blocked" # a gate failed; refine loop owns it
|
|
19
|
+
|
|
20
|
+
# allowed forward transitions; anything else is E_ILLEGAL_TRANSITION
|
|
21
|
+
TRANSITIONS = {
|
|
22
|
+
State.INTENT: {State.EXPANDED},
|
|
23
|
+
State.EXPANDED: {State.ARCHITECTED, State.BLOCKED},
|
|
24
|
+
State.ARCHITECTED: {State.SCAFFOLDED, State.BLOCKED},
|
|
25
|
+
State.SCAFFOLDED: {State.FILLED, State.BLOCKED},
|
|
26
|
+
State.FILLED: {State.REVIEWED, State.BLOCKED},
|
|
27
|
+
State.REVIEWED: {State.ARCH_GATED, State.BLOCKED},
|
|
28
|
+
State.ARCH_GATED: {State.TESTS_VERIFIED, State.BLOCKED},
|
|
29
|
+
State.TESTS_VERIFIED: {State.SMOKED, State.BLOCKED},
|
|
30
|
+
State.SMOKED: {State.SHIPPED, State.BLOCKED},
|
|
31
|
+
State.BLOCKED: {State.SCAFFOLDED, State.FILLED, State.REVIEWED, State.ARCH_GATED, State.TESTS_VERIFIED, State.SMOKED},
|
|
32
|
+
State.SHIPPED: set(),
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
HUMAN_GATES = {State.EXPANDED, State.ARCHITECTED} # confidence gates requiring signoff
|
|
36
|
+
|
|
37
|
+
class IllegalTransition(RuntimeError):
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
def can_transition(frm: State, to: State) -> bool:
|
|
41
|
+
return to in TRANSITIONS.get(frm, set())
|