atomadic-forge 0.3.2__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.
- atomadic_forge/__init__.py +12 -0
- atomadic_forge/__main__.py +5 -0
- atomadic_forge/a0_qk_constants/__init__.py +1 -0
- atomadic_forge/a0_qk_constants/agent_plan_schema.py +120 -0
- atomadic_forge/a0_qk_constants/commandsmith_types.py +49 -0
- atomadic_forge/a0_qk_constants/config_defaults.py +38 -0
- atomadic_forge/a0_qk_constants/emergent_types.py +77 -0
- atomadic_forge/a0_qk_constants/error_codes.py +296 -0
- atomadic_forge/a0_qk_constants/forge_types.py +89 -0
- atomadic_forge/a0_qk_constants/gen_language.py +116 -0
- atomadic_forge/a0_qk_constants/lang_extensions.py +150 -0
- atomadic_forge/a0_qk_constants/policy_schema.py +48 -0
- atomadic_forge/a0_qk_constants/receipt_schema.py +311 -0
- atomadic_forge/a0_qk_constants/roi_constants.py +96 -0
- atomadic_forge/a0_qk_constants/semantic_types.py +61 -0
- atomadic_forge/a0_qk_constants/sidecar_schema.py +81 -0
- atomadic_forge/a0_qk_constants/synergy_types.py +62 -0
- atomadic_forge/a0_qk_constants/tier_names.py +47 -0
- atomadic_forge/a1_at_functions/__init__.py +1 -0
- atomadic_forge/a1_at_functions/agent_context_pack.py +193 -0
- atomadic_forge/a1_at_functions/agent_memory.py +139 -0
- atomadic_forge/a1_at_functions/agent_plan_emitter.py +324 -0
- atomadic_forge/a1_at_functions/agent_summary.py +277 -0
- atomadic_forge/a1_at_functions/body_extractor.py +306 -0
- atomadic_forge/a1_at_functions/card_renderer.py +210 -0
- atomadic_forge/a1_at_functions/certify_checks.py +445 -0
- atomadic_forge/a1_at_functions/chat_context.py +170 -0
- atomadic_forge/a1_at_functions/cherry_pick.py +71 -0
- atomadic_forge/a1_at_functions/classify_tier.py +115 -0
- atomadic_forge/a1_at_functions/commandsmith_discover.py +167 -0
- atomadic_forge/a1_at_functions/commandsmith_render.py +267 -0
- atomadic_forge/a1_at_functions/compiler_feedback.py +94 -0
- atomadic_forge/a1_at_functions/compliance_checker.py +228 -0
- atomadic_forge/a1_at_functions/config_io.py +68 -0
- atomadic_forge/a1_at_functions/cs1_renderer.py +588 -0
- atomadic_forge/a1_at_functions/doc_synthesizer.py +205 -0
- atomadic_forge/a1_at_functions/emergent_compose.py +192 -0
- atomadic_forge/a1_at_functions/emergent_rank.py +116 -0
- atomadic_forge/a1_at_functions/emergent_signature_extract.py +242 -0
- atomadic_forge/a1_at_functions/emergent_synthesize.py +88 -0
- atomadic_forge/a1_at_functions/enforce_planner.py +208 -0
- atomadic_forge/a1_at_functions/error_hints.py +105 -0
- atomadic_forge/a1_at_functions/evolution_log.py +94 -0
- atomadic_forge/a1_at_functions/forge_feedback.py +433 -0
- atomadic_forge/a1_at_functions/generation_quality.py +322 -0
- atomadic_forge/a1_at_functions/import_repair.py +211 -0
- atomadic_forge/a1_at_functions/import_smoke.py +102 -0
- atomadic_forge/a1_at_functions/js_parser.py +539 -0
- atomadic_forge/a1_at_functions/lineage_chain.py +144 -0
- atomadic_forge/a1_at_functions/lineage_reader.py +107 -0
- atomadic_forge/a1_at_functions/llm_client.py +554 -0
- atomadic_forge/a1_at_functions/local_signer.py +134 -0
- atomadic_forge/a1_at_functions/lsp_protocol.py +379 -0
- atomadic_forge/a1_at_functions/manifest_diff.py +314 -0
- atomadic_forge/a1_at_functions/mcp_protocol.py +1066 -0
- atomadic_forge/a1_at_functions/patch_scorer.py +267 -0
- atomadic_forge/a1_at_functions/plan_adapter.py +75 -0
- atomadic_forge/a1_at_functions/policy_loader.py +107 -0
- atomadic_forge/a1_at_functions/preflight_change.py +227 -0
- atomadic_forge/a1_at_functions/progress_reporter.py +81 -0
- atomadic_forge/a1_at_functions/provider_detect.py +157 -0
- atomadic_forge/a1_at_functions/provider_resolver.py +48 -0
- atomadic_forge/a1_at_functions/receipt_emitter.py +291 -0
- atomadic_forge/a1_at_functions/recipes.py +186 -0
- atomadic_forge/a1_at_functions/repo_explainer.py +124 -0
- atomadic_forge/a1_at_functions/roi_calculator.py +265 -0
- atomadic_forge/a1_at_functions/rollback_planner.py +147 -0
- atomadic_forge/a1_at_functions/sbom_emitter.py +155 -0
- atomadic_forge/a1_at_functions/scaffold_js.py +55 -0
- atomadic_forge/a1_at_functions/scaffold_pyproject.py +62 -0
- atomadic_forge/a1_at_functions/scaffold_starter.py +94 -0
- atomadic_forge/a1_at_functions/scout_walk.py +309 -0
- atomadic_forge/a1_at_functions/sidecar_parser.py +161 -0
- atomadic_forge/a1_at_functions/sidecar_validator.py +202 -0
- atomadic_forge/a1_at_functions/stub_detector.py +158 -0
- atomadic_forge/a1_at_functions/synergy_detect.py +166 -0
- atomadic_forge/a1_at_functions/synergy_render.py +252 -0
- atomadic_forge/a1_at_functions/synergy_surface_extract.py +163 -0
- atomadic_forge/a1_at_functions/test_runner.py +196 -0
- atomadic_forge/a1_at_functions/test_selector.py +122 -0
- atomadic_forge/a1_at_functions/tier_init_rebuild.py +122 -0
- atomadic_forge/a1_at_functions/tool_composer.py +130 -0
- atomadic_forge/a1_at_functions/transcript_log.py +70 -0
- atomadic_forge/a1_at_functions/wire_check.py +260 -0
- atomadic_forge/a2_mo_composites/__init__.py +1 -0
- atomadic_forge/a2_mo_composites/lineage_chain_store.py +122 -0
- atomadic_forge/a2_mo_composites/manifest_store.py +46 -0
- atomadic_forge/a2_mo_composites/plan_store.py +164 -0
- atomadic_forge/a2_mo_composites/receipt_signer.py +231 -0
- atomadic_forge/a3_og_features/__init__.py +1 -0
- atomadic_forge/a3_og_features/commandsmith_feature.py +267 -0
- atomadic_forge/a3_og_features/demo_packages/mixed_py_js/src/mixed_pkg/__init__.py +3 -0
- atomadic_forge/a3_og_features/demo_packages/mixed_py_js/src/mixed_pkg/a0_qk_constants/__init__.py +4 -0
- atomadic_forge/a3_og_features/demo_packages/mixed_py_js/src/mixed_pkg/a1_at_functions/__init__.py +14 -0
- atomadic_forge/a3_og_features/demo_packages/mixed_py_js/tests/conftest.py +10 -0
- atomadic_forge/a3_og_features/demo_packages/mixed_py_js/tests/test_mixed.py +18 -0
- atomadic_forge/a3_og_features/demo_runner.py +502 -0
- atomadic_forge/a3_og_features/emergent_feature.py +95 -0
- atomadic_forge/a3_og_features/emergent_pipeline_integration.py +154 -0
- atomadic_forge/a3_og_features/forge_enforce.py +107 -0
- atomadic_forge/a3_og_features/forge_evolve.py +176 -0
- atomadic_forge/a3_og_features/forge_loop.py +528 -0
- atomadic_forge/a3_og_features/forge_pipeline.py +295 -0
- atomadic_forge/a3_og_features/forge_plan_apply.py +222 -0
- atomadic_forge/a3_og_features/lsp_server.py +98 -0
- atomadic_forge/a3_og_features/mcp_server.py +160 -0
- atomadic_forge/a3_og_features/setup_wizard.py +337 -0
- atomadic_forge/a3_og_features/synergy_feature.py +65 -0
- atomadic_forge/a4_sy_orchestration/__init__.py +1 -0
- atomadic_forge/a4_sy_orchestration/cli.py +1284 -0
- atomadic_forge/commands/__init__.py +1 -0
- atomadic_forge/commands/_registry.py +36 -0
- atomadic_forge/commands/audit.py +142 -0
- atomadic_forge/commands/chat.py +133 -0
- atomadic_forge/commands/commandsmith.py +178 -0
- atomadic_forge/commands/config_cmd.py +145 -0
- atomadic_forge/commands/demo.py +142 -0
- atomadic_forge/commands/emergent.py +124 -0
- atomadic_forge/commands/emergent_then_synergy.py +70 -0
- atomadic_forge/commands/evolve.py +122 -0
- atomadic_forge/commands/evolve_then_iterate.py +70 -0
- atomadic_forge/commands/feature_then_emergent.py +111 -0
- atomadic_forge/commands/iterate.py +140 -0
- atomadic_forge/commands/synergy.py +96 -0
- atomadic_forge/commands/synergy_then_emergent.py +70 -0
- atomadic_forge-0.3.2.dist-info/METADATA +471 -0
- atomadic_forge-0.3.2.dist-info/RECORD +131 -0
- atomadic_forge-0.3.2.dist-info/WHEEL +5 -0
- atomadic_forge-0.3.2.dist-info/entry_points.txt +3 -0
- atomadic_forge-0.3.2.dist-info/licenses/LICENSE +15 -0
- atomadic_forge-0.3.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Atomadic Forge — absorb, enforce, emerge.
|
|
2
|
+
|
|
3
|
+
A monadic-architecture engine for absorbing Python or JavaScript /
|
|
4
|
+
TypeScript repositories into a verified 5-tier layout, enforcing layered
|
|
5
|
+
import discipline, and surfacing emergent compositions across the
|
|
6
|
+
resulting catalog.
|
|
7
|
+
|
|
8
|
+
Public version surface only — every symbol lives in its tier package and
|
|
9
|
+
is re-exported lazily by the CLI.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__version__ = "0.3.2"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Tier a0 — constants, types, schema names. Zero logic."""
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""Tier a0 — agent-plan/v1 wire-format schema.
|
|
2
|
+
|
|
3
|
+
Direct response to Codex's follow-up directive after using earlier
|
|
4
|
+
Forge releases:
|
|
5
|
+
|
|
6
|
+
> 'Make Forge output \"next best action cards.\" The active agent
|
|
7
|
+
> then does what agents are good at: inspect files, edit
|
|
8
|
+
> carefully, run tests, decide whether the suggestion was
|
|
9
|
+
> actually good. Forge stays the architectural conscience and
|
|
10
|
+
> candidate generator.'
|
|
11
|
+
|
|
12
|
+
Where ``agent_summary/v1`` (prior commit) was a compact dashboard,
|
|
13
|
+
``agent_plan/v1`` is the operational manifest the agent actually
|
|
14
|
+
executes against. Each ``AgentActionCard`` is a bounded, named,
|
|
15
|
+
applyable proposal: id, why, write_scope, validation commands,
|
|
16
|
+
risk, and whether Forge itself can apply it via existing verbs.
|
|
17
|
+
|
|
18
|
+
a0 invariant: this file holds only TypedDicts + constant strings.
|
|
19
|
+
No logic. Imports limited to ``__future__`` and ``typing``.
|
|
20
|
+
"""
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from typing import Literal, TypedDict
|
|
24
|
+
|
|
25
|
+
SCHEMA_VERSION_AGENT_PLAN_V1 = "atomadic-forge.agent_plan/v1"
|
|
26
|
+
SCHEMA_VERSION_AGENT_ACTION_V1 = "atomadic-forge.agent_action/v1"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Card kinds — pinned for downstream filtering. Adding a new kind is
|
|
30
|
+
# additive; renaming or removing one is a major schema bump.
|
|
31
|
+
ACTION_KINDS: tuple[str, ...] = (
|
|
32
|
+
"operational", # CI / changelog / README / tests-present gaps
|
|
33
|
+
"architectural", # wire violations, F-coded
|
|
34
|
+
"composition", # emergent — symbol chains
|
|
35
|
+
"synthesis", # synergy — feature-pair adapters
|
|
36
|
+
"release", # final-mile (sign Receipt, gate certify ≥ N)
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Plan modes — the agent declares what it wants to do.
|
|
40
|
+
PLAN_MODES: tuple[str, ...] = (
|
|
41
|
+
"improve", # operate on the existing repo in-place
|
|
42
|
+
"absorb", # take a flat repo and emit a new tier-organized package
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Risk levels — drives the agent's confirmation policy.
|
|
46
|
+
RISK_LEVELS: tuple[str, ...] = ("low", "medium", "high")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class AgentActionCard(TypedDict, total=False):
|
|
50
|
+
"""One bounded proposal for the agent to inspect, edit, apply.
|
|
51
|
+
|
|
52
|
+
Required fields:
|
|
53
|
+
schema_version — atomadic-forge.agent_action/v1
|
|
54
|
+
id — stable slug (e.g. 'fix-wire-F0042-helper-py');
|
|
55
|
+
the agent uses this in `auto step <id>`
|
|
56
|
+
kind — one of ACTION_KINDS
|
|
57
|
+
title — one-line human label
|
|
58
|
+
why — 1-3 sentence justification (concrete, no fluff)
|
|
59
|
+
risk — one of RISK_LEVELS
|
|
60
|
+
applyable — true when Forge has a verb that can execute this
|
|
61
|
+
unattended; false means hand to the agent
|
|
62
|
+
|
|
63
|
+
Optional but strongly encouraged:
|
|
64
|
+
write_scope — list of file globs the action will touch
|
|
65
|
+
commands — list of validation commands the agent should
|
|
66
|
+
run AFTER applying (pytest, forge wire, etc.)
|
|
67
|
+
related_fcodes — F-codes this action resolves
|
|
68
|
+
next_command — the single shell command to execute the action
|
|
69
|
+
sample_path — representative file (when applicable)
|
|
70
|
+
score_delta_estimate — expected certify score increase (heuristic)
|
|
71
|
+
"""
|
|
72
|
+
schema_version: str
|
|
73
|
+
id: str
|
|
74
|
+
kind: str
|
|
75
|
+
title: str
|
|
76
|
+
why: str
|
|
77
|
+
risk: str
|
|
78
|
+
applyable: bool
|
|
79
|
+
write_scope: list[str]
|
|
80
|
+
commands: list[str]
|
|
81
|
+
related_fcodes: list[str]
|
|
82
|
+
next_command: str
|
|
83
|
+
sample_path: str | None
|
|
84
|
+
score_delta_estimate: int
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class AgentPlan(TypedDict, total=False):
|
|
88
|
+
"""The plan envelope: ordered top-N actions + meta.
|
|
89
|
+
|
|
90
|
+
Required:
|
|
91
|
+
schema_version, generated_at_utc, verdict, goal, mode,
|
|
92
|
+
top_actions, project_root.
|
|
93
|
+
"""
|
|
94
|
+
schema_version: str
|
|
95
|
+
generated_at_utc: str
|
|
96
|
+
verdict: Literal["PASS", "FAIL", "REFINE", "QUARANTINE"]
|
|
97
|
+
goal: str
|
|
98
|
+
mode: str # one of PLAN_MODES
|
|
99
|
+
project_root: str
|
|
100
|
+
top_actions: list[AgentActionCard]
|
|
101
|
+
action_count: int # full count regardless of top_n cap
|
|
102
|
+
applyable_count: int
|
|
103
|
+
next_command: str
|
|
104
|
+
# Codex feedback: surface the certify score on the plan envelope
|
|
105
|
+
# so MCP _summary digests don't have to guess. None when no
|
|
106
|
+
# certify_report fed the plan.
|
|
107
|
+
score: float | None
|
|
108
|
+
# Provenance — what scans fed into this plan.
|
|
109
|
+
sources: dict[str, str] # {source_name: schema_version}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
REQUIRED_PLAN_FIELDS: tuple[str, ...] = (
|
|
113
|
+
"schema_version",
|
|
114
|
+
"generated_at_utc",
|
|
115
|
+
"verdict",
|
|
116
|
+
"goal",
|
|
117
|
+
"mode",
|
|
118
|
+
"project_root",
|
|
119
|
+
"top_actions",
|
|
120
|
+
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Tier a0 — types for the Commandsmith CLI command-management phase.
|
|
2
|
+
|
|
3
|
+
Commandsmith discovers Python modules that expose CLI commands (existing
|
|
4
|
+
or freshly assimilated) and emits:
|
|
5
|
+
|
|
6
|
+
1. A registry manifest (JSON) describing every known command.
|
|
7
|
+
2. An auto-wired Python registry module that registers all commands on a
|
|
8
|
+
Typer app (replacing the hand-maintained ``register_commands`` shim).
|
|
9
|
+
3. Per-command Markdown docs and an INDEX.
|
|
10
|
+
|
|
11
|
+
These TypedDicts are the wire format for that pipeline. No logic here —
|
|
12
|
+
only data shapes.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import Literal, TypedDict
|
|
18
|
+
|
|
19
|
+
CommandSurface = Literal["typer_app", "register_fn", "wrapped_class"]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CommandSignatureCard(TypedDict):
|
|
23
|
+
"""One sub-command's parameter signature as a small dict-of-strings."""
|
|
24
|
+
|
|
25
|
+
name: str
|
|
26
|
+
parameters: list[str] # e.g. ["repo: Path", "--tier (a0|a1|...): str"]
|
|
27
|
+
return_type: str # e.g. "ReconReport"
|
|
28
|
+
docstring: str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class RegisteredCommandCard(TypedDict):
|
|
32
|
+
"""Static description of one CLI command discovered by Commandsmith."""
|
|
33
|
+
|
|
34
|
+
name: str # CLI verb (e.g. "cherry-pick")
|
|
35
|
+
module: str # Python module path
|
|
36
|
+
surface: CommandSurface # how the module exposes commands
|
|
37
|
+
help_text: str # one-line description
|
|
38
|
+
hidden: bool
|
|
39
|
+
sub_commands: list[CommandSignatureCard]
|
|
40
|
+
source_root: str # which root contributed it ("atomadic_forge_seed", "atomadic_v2", ...)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class RegistryManifestCard(TypedDict):
|
|
44
|
+
"""Persistent registry of every command Commandsmith has wired."""
|
|
45
|
+
|
|
46
|
+
schema_version: str # "atomadic-forge.commandsmith.registry/v1"
|
|
47
|
+
generated_at_utc: str
|
|
48
|
+
commands: list[RegisteredCommandCard]
|
|
49
|
+
smoke_results: dict[str, bool] # cmd-name -> --help exit 0?
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Tier a0 — config defaults and file-location constants for Atomadic Forge."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TypedDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ForgeConfig(TypedDict, total=False):
|
|
9
|
+
provider: str
|
|
10
|
+
ollama_url: str
|
|
11
|
+
ollama_model: str
|
|
12
|
+
gemini_key: str | None
|
|
13
|
+
anthropic_key: str | None
|
|
14
|
+
openai_key: str | None
|
|
15
|
+
default_target_score: float
|
|
16
|
+
auto_apply: bool
|
|
17
|
+
output_dir: str
|
|
18
|
+
sources_dir: str
|
|
19
|
+
package_prefix: str
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
DEFAULT_CONFIG: ForgeConfig = {
|
|
23
|
+
"provider": "auto",
|
|
24
|
+
"ollama_url": "http://localhost:11434",
|
|
25
|
+
"ollama_model": "mistral:7b-instruct",
|
|
26
|
+
"gemini_key": None,
|
|
27
|
+
"anthropic_key": None,
|
|
28
|
+
"openai_key": None,
|
|
29
|
+
"default_target_score": 75.0,
|
|
30
|
+
"auto_apply": False,
|
|
31
|
+
"output_dir": "./forged",
|
|
32
|
+
"sources_dir": "./sources",
|
|
33
|
+
"package_prefix": "forged",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
CONFIG_FILE_NAME = "config.json"
|
|
37
|
+
GLOBAL_CONFIG_DIR = "~/.atomadic-forge"
|
|
38
|
+
LOCAL_CONFIG_DIR = ".atomadic-forge"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Tier a0 — types for the Emergent Behaviors Scan.
|
|
2
|
+
|
|
3
|
+
Emergent Scan reads the existing tier-organized catalog and synthesizes
|
|
4
|
+
*new* features by composing components that nobody wired together yet.
|
|
5
|
+
|
|
6
|
+
Pipeline:
|
|
7
|
+
|
|
8
|
+
symbols → signatures (a1) → composition graph (a1) → candidates (a1)
|
|
9
|
+
↓
|
|
10
|
+
optional synthesis (a1) → a3 feature
|
|
11
|
+
|
|
12
|
+
These TypedDicts are the wire format between those steps. No logic here.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import Literal, TypedDict
|
|
18
|
+
|
|
19
|
+
Tier = Literal[
|
|
20
|
+
"a0_qk_constants",
|
|
21
|
+
"a1_at_functions",
|
|
22
|
+
"a2_mo_composites",
|
|
23
|
+
"a3_og_features",
|
|
24
|
+
"a4_sy_orchestration",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SymbolSignatureCard(TypedDict):
|
|
29
|
+
"""One callable's typed surface, tier, and domain tag."""
|
|
30
|
+
|
|
31
|
+
name: str # bare function/class name (e.g. ``infer_tier``)
|
|
32
|
+
qualname: str # module-qualified (e.g. ``atomadic_forge.a1_at_functions.foo.bar``)
|
|
33
|
+
module: str # importable module path
|
|
34
|
+
tier: str # one of Tier
|
|
35
|
+
domain: str # heuristic group (``kg``, ``swarm``, ``cherry`` …)
|
|
36
|
+
inputs: list[tuple[str, str]] # [(param_name, type_annotation_text), …]
|
|
37
|
+
output: str # return annotation text (or "Any")
|
|
38
|
+
is_pure: bool # heuristic: no obvious I/O / mutable state
|
|
39
|
+
docstring: str # one-line
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class CompositionChain(TypedDict):
|
|
43
|
+
"""An ordered chain of symbols where each output feeds the next."""
|
|
44
|
+
|
|
45
|
+
chain: list[str] # qualnames in execution order
|
|
46
|
+
bridges: list[str] # type-text describing each consumed-output edge
|
|
47
|
+
tiers: list[str] # tier of each step
|
|
48
|
+
domains: list[str] # domain tag of each step
|
|
49
|
+
crosses_domains: int # number of distinct domains involved
|
|
50
|
+
crosses_tiers: int # number of distinct tiers involved
|
|
51
|
+
final_output_type: str
|
|
52
|
+
pure: bool # all steps inferred pure
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class EmergentCandidateCard(TypedDict):
|
|
56
|
+
"""A scored synthesis candidate ready for review or materialisation."""
|
|
57
|
+
|
|
58
|
+
candidate_id: str # short hash identifier
|
|
59
|
+
name: str # heuristic kebab-case name
|
|
60
|
+
summary: str # 1-line description
|
|
61
|
+
chain: CompositionChain
|
|
62
|
+
score: float # 0..100
|
|
63
|
+
score_breakdown: dict[str, float]
|
|
64
|
+
suggested_tier: str
|
|
65
|
+
novelty_signals: list[str] # why this is "emergent"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class EmergentScanReport(TypedDict):
|
|
69
|
+
"""Top-level wire format produced by ``atomadic-forge emergent scan --json``."""
|
|
70
|
+
|
|
71
|
+
schema_version: str # "atomadic-forge.emergent.scan/v1"
|
|
72
|
+
generated_at_utc: str
|
|
73
|
+
catalog_size: int
|
|
74
|
+
chain_count_considered: int
|
|
75
|
+
candidates: list[EmergentCandidateCard]
|
|
76
|
+
domain_inventory: dict[str, int]
|
|
77
|
+
tier_inventory: dict[str, int]
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"""Tier a0 — F-code registry: stable, citeable error codes.
|
|
2
|
+
|
|
3
|
+
Golden Path Lane A W5 deliverable. Every error Forge surfaces (wire
|
|
4
|
+
violations, certify failures, scout misclassifications, …) carries an
|
|
5
|
+
``F-code`` of the form ``F0042``: a 4-digit, zero-padded, fixed
|
|
6
|
+
integer that is **never reused or renumbered**. Once an F-code is
|
|
7
|
+
assigned to a class of error, that mapping is part of the schema
|
|
8
|
+
contract — the same way ``schema_version`` is.
|
|
9
|
+
|
|
10
|
+
Why F-codes:
|
|
11
|
+
* Linker-style citeability — a CI report can say "F0042 occurred 3
|
|
12
|
+
times" without leaking the underlying message string, which
|
|
13
|
+
reviewers and tooling can grep / pivot / dashboards on.
|
|
14
|
+
* Machine-applicable ``--fix`` — Lane A W6's ``forge enforce``
|
|
15
|
+
routes by F-code: F0042 has a known mechanical fix (move the
|
|
16
|
+
importing file up to the higher tier), F0050 (no README) has
|
|
17
|
+
another, etc.
|
|
18
|
+
* Forward-compat — adding an F-code is additive. Removing or
|
|
19
|
+
renumbering an F-code is a major schema bump.
|
|
20
|
+
* Internationalization-ready — the message string can change per
|
|
21
|
+
locale; the F-code stays.
|
|
22
|
+
|
|
23
|
+
Registry convention:
|
|
24
|
+
F0001..F0009 — scout / classification (info)
|
|
25
|
+
F0010..F0019 — cherry-pick (warn)
|
|
26
|
+
F0040..F0049 — wire / upward-import violations ← W5 seeds these
|
|
27
|
+
F0050..F0059 — certify axis failures ← W5 seeds these
|
|
28
|
+
F0060..F0069 — stub detection
|
|
29
|
+
F0070..F0079 — import-repair
|
|
30
|
+
F0080..F0089 — assimilate conflicts
|
|
31
|
+
F0090..F0099 — receipt / signing
|
|
32
|
+
|
|
33
|
+
Pure data: this module imports only ``__future__`` and ``typing``.
|
|
34
|
+
The lookup helpers are pure.
|
|
35
|
+
"""
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
from typing import Literal, TypedDict
|
|
39
|
+
|
|
40
|
+
FCodeSeverity = Literal["info", "warn", "error"]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class FCode(TypedDict):
|
|
44
|
+
"""One entry in the F-code registry.
|
|
45
|
+
|
|
46
|
+
Fields:
|
|
47
|
+
code — 'F' + 4 zero-padded digits (e.g. 'F0042')
|
|
48
|
+
name — short kebab-case slug (stable; never renamed)
|
|
49
|
+
severity — info | warn | error
|
|
50
|
+
title — one-line human label (may be localized)
|
|
51
|
+
hint_key — name of an a1.error_hints template; '' for none
|
|
52
|
+
auto_fixable — when True, Lane A W6 'forge enforce' has a
|
|
53
|
+
mechanical fix path
|
|
54
|
+
doc_anchor — section anchor in docs/F_CODES.md (forthcoming)
|
|
55
|
+
"""
|
|
56
|
+
code: str
|
|
57
|
+
name: str
|
|
58
|
+
severity: FCodeSeverity
|
|
59
|
+
title: str
|
|
60
|
+
hint_key: str
|
|
61
|
+
auto_fixable: bool
|
|
62
|
+
doc_anchor: str
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
F_CODE_REGISTRY: dict[str, FCode] = {
|
|
66
|
+
# ---- Wire / upward-import violations (F0040-F0049) ----
|
|
67
|
+
"F0040": FCode(
|
|
68
|
+
code="F0040",
|
|
69
|
+
name="a0-cannot-import-anything",
|
|
70
|
+
severity="error",
|
|
71
|
+
title="a0_qk_constants must not import any other tier (a0 holds zero logic).",
|
|
72
|
+
hint_key="wire_fail_with_violations",
|
|
73
|
+
auto_fixable=False,
|
|
74
|
+
doc_anchor="f0040-a0-cannot-import-anything",
|
|
75
|
+
),
|
|
76
|
+
"F0041": FCode(
|
|
77
|
+
code="F0041",
|
|
78
|
+
name="a1-imports-a2",
|
|
79
|
+
severity="error",
|
|
80
|
+
title="a1_at_functions imports from a2_mo_composites (upward).",
|
|
81
|
+
hint_key="wire_fail_with_violations",
|
|
82
|
+
auto_fixable=True,
|
|
83
|
+
doc_anchor="f0041-a1-imports-a2",
|
|
84
|
+
),
|
|
85
|
+
"F0042": FCode(
|
|
86
|
+
code="F0042",
|
|
87
|
+
name="a1-imports-a3",
|
|
88
|
+
severity="error",
|
|
89
|
+
title="a1_at_functions imports from a3_og_features (upward).",
|
|
90
|
+
hint_key="wire_fail_with_violations",
|
|
91
|
+
auto_fixable=True,
|
|
92
|
+
doc_anchor="f0042-a1-imports-a3",
|
|
93
|
+
),
|
|
94
|
+
"F0043": FCode(
|
|
95
|
+
code="F0043",
|
|
96
|
+
name="a1-imports-a4",
|
|
97
|
+
severity="error",
|
|
98
|
+
title="a1_at_functions imports from a4_sy_orchestration (upward).",
|
|
99
|
+
hint_key="wire_fail_with_violations",
|
|
100
|
+
auto_fixable=True,
|
|
101
|
+
doc_anchor="f0043-a1-imports-a4",
|
|
102
|
+
),
|
|
103
|
+
"F0044": FCode(
|
|
104
|
+
code="F0044",
|
|
105
|
+
name="a2-imports-a3",
|
|
106
|
+
severity="error",
|
|
107
|
+
title="a2_mo_composites imports from a3_og_features (upward).",
|
|
108
|
+
hint_key="wire_fail_with_violations",
|
|
109
|
+
auto_fixable=True,
|
|
110
|
+
doc_anchor="f0044-a2-imports-a3",
|
|
111
|
+
),
|
|
112
|
+
"F0045": FCode(
|
|
113
|
+
code="F0045",
|
|
114
|
+
name="a2-imports-a4",
|
|
115
|
+
severity="error",
|
|
116
|
+
title="a2_mo_composites imports from a4_sy_orchestration (upward).",
|
|
117
|
+
hint_key="wire_fail_with_violations",
|
|
118
|
+
auto_fixable=True,
|
|
119
|
+
doc_anchor="f0045-a2-imports-a4",
|
|
120
|
+
),
|
|
121
|
+
"F0046": FCode(
|
|
122
|
+
code="F0046",
|
|
123
|
+
name="a3-imports-a4",
|
|
124
|
+
severity="error",
|
|
125
|
+
title="a3_og_features imports from a4_sy_orchestration (upward).",
|
|
126
|
+
hint_key="wire_fail_with_violations",
|
|
127
|
+
auto_fixable=True,
|
|
128
|
+
doc_anchor="f0046-a3-imports-a4",
|
|
129
|
+
),
|
|
130
|
+
"F0049": FCode(
|
|
131
|
+
code="F0049",
|
|
132
|
+
name="unknown-tier-violation",
|
|
133
|
+
severity="error",
|
|
134
|
+
title="Upward import detected but tier shape is non-canonical; review manually.",
|
|
135
|
+
hint_key="wire_fail_with_violations",
|
|
136
|
+
auto_fixable=False,
|
|
137
|
+
doc_anchor="f0049-unknown-tier-violation",
|
|
138
|
+
),
|
|
139
|
+
# ---- Certify axis failures (F0050-F0059) ----
|
|
140
|
+
"F0050": FCode(
|
|
141
|
+
code="F0050",
|
|
142
|
+
name="documentation-missing",
|
|
143
|
+
severity="error",
|
|
144
|
+
title="Documentation axis FAIL: no README.md and < 2 docs/*.md files.",
|
|
145
|
+
hint_key="certify_below_threshold",
|
|
146
|
+
auto_fixable=True,
|
|
147
|
+
doc_anchor="f0050-documentation-missing",
|
|
148
|
+
),
|
|
149
|
+
"F0051": FCode(
|
|
150
|
+
code="F0051",
|
|
151
|
+
name="tests-missing",
|
|
152
|
+
severity="error",
|
|
153
|
+
title="Tests axis FAIL: no tests/test_*.py or tests/*_test.py present.",
|
|
154
|
+
hint_key="certify_below_threshold",
|
|
155
|
+
auto_fixable=False,
|
|
156
|
+
doc_anchor="f0051-tests-missing",
|
|
157
|
+
),
|
|
158
|
+
"F0052": FCode(
|
|
159
|
+
code="F0052",
|
|
160
|
+
name="tier-layout-incomplete",
|
|
161
|
+
severity="error",
|
|
162
|
+
title="Tier-layout axis FAIL: fewer than 3 tier directories present.",
|
|
163
|
+
hint_key="no_tier_dirs",
|
|
164
|
+
auto_fixable=False,
|
|
165
|
+
doc_anchor="f0052-tier-layout-incomplete",
|
|
166
|
+
),
|
|
167
|
+
"F0053": FCode(
|
|
168
|
+
code="F0053",
|
|
169
|
+
name="upward-imports-present",
|
|
170
|
+
severity="error",
|
|
171
|
+
title="Import-discipline axis FAIL: at least one wire violation present.",
|
|
172
|
+
hint_key="wire_fail_with_violations",
|
|
173
|
+
auto_fixable=True,
|
|
174
|
+
doc_anchor="f0053-upward-imports-present",
|
|
175
|
+
),
|
|
176
|
+
# ---- Sidecar drift (F0100-F0109; Lane D W8/W11) ----
|
|
177
|
+
"F0100": FCode(
|
|
178
|
+
code="F0100",
|
|
179
|
+
name="sidecar-source-unparseable",
|
|
180
|
+
severity="error",
|
|
181
|
+
title="Sidecar present but the source file did not parse.",
|
|
182
|
+
hint_key="",
|
|
183
|
+
auto_fixable=False,
|
|
184
|
+
doc_anchor="f0100-sidecar-source-unparseable",
|
|
185
|
+
),
|
|
186
|
+
"F0101": FCode(
|
|
187
|
+
code="F0101",
|
|
188
|
+
name="sidecar-declares-missing-symbol",
|
|
189
|
+
severity="error",
|
|
190
|
+
title="Sidecar declares a symbol the source file doesn't have.",
|
|
191
|
+
hint_key="",
|
|
192
|
+
auto_fixable=False,
|
|
193
|
+
doc_anchor="f0101-sidecar-declares-missing-symbol",
|
|
194
|
+
),
|
|
195
|
+
"F0102": FCode(
|
|
196
|
+
code="F0102",
|
|
197
|
+
name="sidecar-coverage-incomplete",
|
|
198
|
+
severity="warn",
|
|
199
|
+
title="Source has a public symbol the sidecar didn't declare (advisory).",
|
|
200
|
+
hint_key="",
|
|
201
|
+
auto_fixable=False,
|
|
202
|
+
doc_anchor="f0102-sidecar-coverage-incomplete",
|
|
203
|
+
),
|
|
204
|
+
"F0103": FCode(
|
|
205
|
+
code="F0103",
|
|
206
|
+
name="sidecar-pure-violates-purity",
|
|
207
|
+
severity="error",
|
|
208
|
+
title="Sidecar declares Pure but source uses I/O / network / non-deterministic input.",
|
|
209
|
+
hint_key="",
|
|
210
|
+
auto_fixable=False,
|
|
211
|
+
doc_anchor="f0103-sidecar-pure-violates-purity",
|
|
212
|
+
),
|
|
213
|
+
"F0106": FCode(
|
|
214
|
+
code="F0106",
|
|
215
|
+
name="sidecar-tier-mismatch",
|
|
216
|
+
severity="warn",
|
|
217
|
+
title="Sidecar declares a tier different from the source file's actual path tier.",
|
|
218
|
+
hint_key="",
|
|
219
|
+
auto_fixable=False,
|
|
220
|
+
doc_anchor="f0106-sidecar-tier-mismatch",
|
|
221
|
+
),
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
# Sidecar S-code → F-code mapping. Exposed so the validator (a1) can
|
|
226
|
+
# promote local drift labels into the global F-code namespace
|
|
227
|
+
# without re-importing this whole registry.
|
|
228
|
+
SIDECAR_S_TO_F: dict[str, str] = {
|
|
229
|
+
"S0000": "F0100",
|
|
230
|
+
"S0001": "F0101",
|
|
231
|
+
"S0002": "F0102",
|
|
232
|
+
"S0003": "F0103",
|
|
233
|
+
"S0006": "F0106",
|
|
234
|
+
}
|
|
235
|
+
"""Canonical F-code registry. Adding a new code is additive; renaming
|
|
236
|
+
or renumbering is a major schema bump (and requires updating every
|
|
237
|
+
test and consumer). See the H1 pre-audit smoke for the drift sentinel.
|
|
238
|
+
"""
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
_TIER_PAIR_TO_FCODE: dict[tuple[str, str], str] = {
|
|
242
|
+
# (from_tier, to_tier) → F-code. a0 is special-cased below.
|
|
243
|
+
("a1_at_functions", "a2_mo_composites"): "F0041",
|
|
244
|
+
("a1_at_functions", "a3_og_features"): "F0042",
|
|
245
|
+
("a1_at_functions", "a4_sy_orchestration"): "F0043",
|
|
246
|
+
("a2_mo_composites", "a3_og_features"): "F0044",
|
|
247
|
+
("a2_mo_composites", "a4_sy_orchestration"): "F0045",
|
|
248
|
+
("a3_og_features", "a4_sy_orchestration"): "F0046",
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def fcode_for_tier_violation(from_tier: str, to_tier: str) -> str:
|
|
253
|
+
"""Map a (from, to) tier pair to its registered F-code.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
'F0040' when from_tier is a0 (a0 may not import anything)
|
|
257
|
+
one of F0041..F0046 for the canonical upward-import pairs
|
|
258
|
+
'F0049' for any other shape (non-canonical tier, mixed-language)
|
|
259
|
+
|
|
260
|
+
Pure: O(1) lookup.
|
|
261
|
+
"""
|
|
262
|
+
if from_tier == "a0_qk_constants":
|
|
263
|
+
return "F0040"
|
|
264
|
+
return _TIER_PAIR_TO_FCODE.get((from_tier, to_tier), "F0049")
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def fcode_for_certify_axis(axis: str) -> str:
|
|
268
|
+
"""Map a certify axis name to its F-code.
|
|
269
|
+
|
|
270
|
+
Recognised axis names match the CertifyResult booleans:
|
|
271
|
+
'documentation_complete' → F0050
|
|
272
|
+
'tests_present' → F0051
|
|
273
|
+
'tier_layout_present' → F0052
|
|
274
|
+
'no_upward_imports' → F0053
|
|
275
|
+
Unknown axes return '' (no F-code assigned).
|
|
276
|
+
"""
|
|
277
|
+
return {
|
|
278
|
+
"documentation_complete": "F0050",
|
|
279
|
+
"tests_present": "F0051",
|
|
280
|
+
"tier_layout_present": "F0052",
|
|
281
|
+
"no_upward_imports": "F0053",
|
|
282
|
+
}.get(axis, "")
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def get_fcode(code: str) -> FCode | None:
|
|
286
|
+
"""Return the registry entry for ``code`` or None if unregistered."""
|
|
287
|
+
return F_CODE_REGISTRY.get(code)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def all_auto_fixable_fcodes() -> tuple[str, ...]:
|
|
291
|
+
"""Return the codes Lane A W6 'forge enforce' has a path for.
|
|
292
|
+
|
|
293
|
+
Sorted ascending so consumers get a stable iteration order.
|
|
294
|
+
"""
|
|
295
|
+
return tuple(sorted(c for c, e in F_CODE_REGISTRY.items()
|
|
296
|
+
if e["auto_fixable"]))
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Tier a0 — Forge-specific report shapes.
|
|
2
|
+
|
|
3
|
+
Wire formats for scout / cherry-pick / wire / certify / assimilate output.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Literal, TypedDict
|
|
9
|
+
|
|
10
|
+
SymbolKind = Literal["function", "class", "method"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SymbolRecord(TypedDict):
|
|
14
|
+
"""One callable discovered in a target repo."""
|
|
15
|
+
|
|
16
|
+
name: str
|
|
17
|
+
qualname: str # e.g. "Counter.incr"
|
|
18
|
+
kind: SymbolKind
|
|
19
|
+
file: str # repo-relative path
|
|
20
|
+
lineno: int
|
|
21
|
+
tier_guess: str # one of TIER_NAMES
|
|
22
|
+
effects: list[str] # ["pure"], ["io"], etc.
|
|
23
|
+
complexity: int # ast.dump length (cheap proxy)
|
|
24
|
+
has_self_assign: bool
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ScoutReport(TypedDict):
|
|
28
|
+
schema_version: str # "atomadic-forge.scout/v1"
|
|
29
|
+
repo: str
|
|
30
|
+
file_count: int
|
|
31
|
+
python_file_count: int
|
|
32
|
+
symbol_count: int
|
|
33
|
+
tier_distribution: dict[str, int]
|
|
34
|
+
effect_distribution: dict[str, int]
|
|
35
|
+
symbols: list[SymbolRecord]
|
|
36
|
+
recommendations: list[str]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class CherryPickItem(TypedDict):
|
|
40
|
+
qualname: str
|
|
41
|
+
target_tier: str
|
|
42
|
+
confidence: float
|
|
43
|
+
reasons: list[str]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class CherryPickManifest(TypedDict):
|
|
47
|
+
schema_version: str # "atomadic-forge.cherry/v1"
|
|
48
|
+
source_repo: str
|
|
49
|
+
items: list[CherryPickItem]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class WireViolation(TypedDict):
|
|
53
|
+
file: str
|
|
54
|
+
from_tier: str
|
|
55
|
+
to_tier: str
|
|
56
|
+
imported: str
|
|
57
|
+
proposed_fix: str # rewritten import line, or "" if no fix found
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class WireReport(TypedDict):
|
|
61
|
+
schema_version: str # "atomadic-forge.wire/v1"
|
|
62
|
+
source_dir: str
|
|
63
|
+
violation_count: int
|
|
64
|
+
auto_fixable: int
|
|
65
|
+
violations: list[WireViolation]
|
|
66
|
+
verdict: Literal["PASS", "FAIL"]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class CertifyResult(TypedDict):
|
|
70
|
+
schema_version: str # "atomadic-forge.certify/v1"
|
|
71
|
+
project: str
|
|
72
|
+
timestamp: str
|
|
73
|
+
documentation_complete: bool
|
|
74
|
+
tests_present: bool
|
|
75
|
+
tier_layout_present: bool
|
|
76
|
+
no_upward_imports: bool
|
|
77
|
+
score: float # 0..100
|
|
78
|
+
issues: list[str]
|
|
79
|
+
recommendations: list[str]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class AssimilateReport(TypedDict):
|
|
83
|
+
schema_version: str # "atomadic-forge.assimilate/v1"
|
|
84
|
+
target_root: str
|
|
85
|
+
source_repos: list[str]
|
|
86
|
+
components_emitted: int
|
|
87
|
+
tier_distribution: dict[str, int]
|
|
88
|
+
files_repaired: int
|
|
89
|
+
digest: str
|