archkeel 0.1.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.
- archkeel-0.1.0/.gitignore +11 -0
- archkeel-0.1.0/LICENSE +21 -0
- archkeel-0.1.0/Makefile +29 -0
- archkeel-0.1.0/PKG-INFO +355 -0
- archkeel-0.1.0/README.md +331 -0
- archkeel-0.1.0/architecture-contract.json +330 -0
- archkeel-0.1.0/archkeel.toml +4 -0
- archkeel-0.1.0/docs/architecture/archkeel.md +7 -0
- archkeel-0.1.0/docs/assets/archkeel-hero.png +0 -0
- archkeel-0.1.0/docs/assets/archkeel-report-preview.png +0 -0
- archkeel-0.1.0/docs/reference.md +124 -0
- archkeel-0.1.0/docs/report-visual-system.md +166 -0
- archkeel-0.1.0/docs/roadmap.md +9 -0
- archkeel-0.1.0/fixtures/A-dispatch/.gitkeep +0 -0
- archkeel-0.1.0/fixtures/A-dispatch/after.py +9 -0
- archkeel-0.1.0/fixtures/A-dispatch/before.py +8 -0
- archkeel-0.1.0/fixtures/B-posthoc/.gitkeep +0 -0
- archkeel-0.1.0/fixtures/B-posthoc/after.py +9 -0
- archkeel-0.1.0/fixtures/B-posthoc/before.py +8 -0
- archkeel-0.1.0/fixtures/C-valid/after.py +9 -0
- archkeel-0.1.0/fixtures/C-valid/before.py +8 -0
- archkeel-0.1.0/fixtures/D-self/architecture.json +1 -0
- archkeel-0.1.0/fixtures/D-self/provenance.json +10 -0
- archkeel-0.1.0/fixtures/D-self/result.json +1 -0
- archkeel-0.1.0/fixtures/E-runtime/archkeel.toml +4 -0
- archkeel-0.1.0/fixtures/E-runtime/docs/architecture/architecture-contract.json +16 -0
- archkeel-0.1.0/fixtures/E-runtime/pyproject.toml +4 -0
- archkeel-0.1.0/fixtures/E-runtime/sample/probe.py +8 -0
- archkeel-0.1.0/fixtures/reproduce_milestone1.py +270 -0
- archkeel-0.1.0/pyproject.toml +87 -0
- archkeel-0.1.0/schema/architecture-ir-common.schema.json +165 -0
- archkeel-0.1.0/schema/architecture-ir-python-decoded.schema.json +753 -0
- archkeel-0.1.0/schema/archkeel.schema.json +53 -0
- archkeel-0.1.0/src/archkeel/__init__.py +3 -0
- archkeel-0.1.0/src/archkeel/accept/__init__.py +21 -0
- archkeel-0.1.0/src/archkeel/check/__init__.py +3 -0
- archkeel-0.1.0/src/archkeel/check/assets/archkeel-logo-dark.svg +12 -0
- archkeel-0.1.0/src/archkeel/check/assets/archkeel-logo-light.svg +10 -0
- archkeel-0.1.0/src/archkeel/check/assets/archkeel-mark.png +0 -0
- archkeel-0.1.0/src/archkeel/check/assets/archkeel-mark.svg +7 -0
- archkeel-0.1.0/src/archkeel/check/assets/archkeel-report.css +350 -0
- archkeel-0.1.0/src/archkeel/check/delta.py +543 -0
- archkeel-0.1.0/src/archkeel/check/expectation.py +383 -0
- archkeel-0.1.0/src/archkeel/check/git.py +90 -0
- archkeel-0.1.0/src/archkeel/check/html.py +320 -0
- archkeel-0.1.0/src/archkeel/check/ordering.py +44 -0
- archkeel-0.1.0/src/archkeel/check/ports.py +45 -0
- archkeel-0.1.0/src/archkeel/check/python_profile.py +23 -0
- archkeel-0.1.0/src/archkeel/check/ratchets.py +100 -0
- archkeel-0.1.0/src/archkeel/check/report.py +107 -0
- archkeel-0.1.0/src/archkeel/check/run.py +205 -0
- archkeel-0.1.0/src/archkeel/check/snapshot.py +174 -0
- archkeel-0.1.0/src/archkeel/cli/__init__.py +93 -0
- archkeel-0.1.0/src/archkeel/cli/__main__.py +6 -0
- archkeel-0.1.0/src/archkeel/cli/config.py +116 -0
- archkeel-0.1.0/src/archkeel/host/__init__.py +4 -0
- archkeel-0.1.0/src/archkeel/host/gitlab.py +93 -0
- archkeel-0.1.0/src/archkeel/host/records.py +61 -0
- archkeel-0.1.0/src/archkeel/ir/__init__.py +3 -0
- archkeel-0.1.0/src/archkeel/ir/codec.py +798 -0
- archkeel-0.1.0/src/archkeel/ir/digest.py +21 -0
- archkeel-0.1.0/src/archkeel/ir/lock.py +41 -0
- archkeel-0.1.0/src/archkeel/ir/measurements.py +67 -0
- archkeel-0.1.0/src/archkeel/ir/model.py +353 -0
- archkeel-0.1.0/src/archkeel/ir/trace.py +91 -0
- archkeel-0.1.0/src/archkeel/producer/__init__.py +166 -0
- archkeel-0.1.0/src/archkeel/producer/bridge.py +30 -0
- archkeel-0.1.0/src/archkeel/producer/embedded/__init__.py +4 -0
- archkeel-0.1.0/src/archkeel/producer/embedded/contract.py +387 -0
- archkeel-0.1.0/src/archkeel/producer/embedded/graph.py +121 -0
- archkeel-0.1.0/src/archkeel/producer/embedded/records.py +63 -0
- archkeel-0.1.0/src/archkeel/producer/embedded/report.py +430 -0
- archkeel-0.1.0/src/archkeel/producer/embedded/scanner.py +1992 -0
- archkeel-0.1.0/src/archkeel/producer/runtime.py +48 -0
- archkeel-0.1.0/src/archkeel/py.typed +0 -0
- archkeel-0.1.0/tests/port-manifest.json +54 -0
- archkeel-0.1.0/tests/smoke_test.py +81 -0
- archkeel-0.1.0/tests/test_check_diagnostics.py +83 -0
- archkeel-0.1.0/tests/test_cli.py +53 -0
- archkeel-0.1.0/tests/test_codec.py +96 -0
- archkeel-0.1.0/tests/test_config.py +120 -0
- archkeel-0.1.0/tests/test_delta.py +310 -0
- archkeel-0.1.0/tests/test_delta_parity.py +55 -0
- archkeel-0.1.0/tests/test_diagnostics.py +41 -0
- archkeel-0.1.0/tests/test_expectation.py +425 -0
- archkeel-0.1.0/tests/test_extraction_boundaries.py +160 -0
- archkeel-0.1.0/tests/test_git_lock.py +184 -0
- archkeel-0.1.0/tests/test_host_gitlab.py +90 -0
- archkeel-0.1.0/tests/test_html_report.py +72 -0
- archkeel-0.1.0/tests/test_lock_diagnostics.py +70 -0
- archkeel-0.1.0/tests/test_model.py +102 -0
- archkeel-0.1.0/tests/test_ordering.py +71 -0
- archkeel-0.1.0/tests/test_producer.py +123 -0
- archkeel-0.1.0/tests/test_ratchets.py +326 -0
- archkeel-0.1.0/tests/test_report_diagnostics.py +73 -0
- archkeel-0.1.0/tests/test_repository_hygiene.py +50 -0
- archkeel-0.1.0/tests/test_runtime.py +133 -0
- archkeel-0.1.0/tests/test_runtime_delta.py +81 -0
- archkeel-0.1.0/tests/test_self.py +102 -0
- archkeel-0.1.0/tests/test_snapshot.py +137 -0
- archkeel-0.1.0/tests/test_source_types.py +44 -0
- archkeel-0.1.0/tests/test_trace.py +31 -0
- archkeel-0.1.0/uv.lock +178 -0
archkeel-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rapiddweller Asia Co., Ltd.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
archkeel-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
.DEFAULT_GOAL := check
|
|
2
|
+
UV ?= uv
|
|
3
|
+
|
|
4
|
+
.PHONY: check test lint typecheck fixtures build smoke release-check
|
|
5
|
+
check: lint typecheck test
|
|
6
|
+
|
|
7
|
+
release-check: check build smoke
|
|
8
|
+
|
|
9
|
+
test:
|
|
10
|
+
$(UV) run --locked python -m pytest -q
|
|
11
|
+
|
|
12
|
+
lint:
|
|
13
|
+
$(UV) run --locked ruff format --check src tests fixtures/reproduce_milestone1.py
|
|
14
|
+
$(UV) run --locked ruff check src tests fixtures/reproduce_milestone1.py
|
|
15
|
+
|
|
16
|
+
typecheck:
|
|
17
|
+
$(UV) run --locked mypy src/archkeel
|
|
18
|
+
|
|
19
|
+
fixtures:
|
|
20
|
+
$(UV) run --locked python fixtures/reproduce_milestone1.py $(if $(OUTPUT),--output "$(OUTPUT)")
|
|
21
|
+
|
|
22
|
+
# Twine validates PyPI metadata; it is a build-only tool.
|
|
23
|
+
build:
|
|
24
|
+
$(UV) build --no-sources --clear
|
|
25
|
+
$(UV) tool run --from twine==7.0.0 twine check --strict dist/*
|
|
26
|
+
|
|
27
|
+
smoke:
|
|
28
|
+
$(UV) run --isolated --no-project --with dist/*.whl tests/smoke_test.py
|
|
29
|
+
$(UV) run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py
|
archkeel-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: archkeel
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Deterministic architecture checks for AI-assisted code changes
|
|
5
|
+
Project-URL: Repository, https://github.com/rapiddweller/archkeel
|
|
6
|
+
Project-URL: Documentation, https://github.com/rapiddweller/archkeel/blob/main/docs/reference.md
|
|
7
|
+
Project-URL: Issues, https://github.com/rapiddweller/archkeel/issues
|
|
8
|
+
Author: Rapiddweller Asia Co., Ltd.
|
|
9
|
+
Maintainer-email: Alexander Kell <Alexander.Kell@rapiddweller.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai-assisted,architecture,cli,code-review,static-analysis
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: packaging<27,>=24.2
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# Archkeel
|
|
26
|
+
|
|
27
|
+
**The agent declares before it submits. The check is deterministic.**
|
|
28
|
+
|
|
29
|
+
<p>
|
|
30
|
+
<img src="https://raw.githubusercontent.com/rapiddweller/archkeel/main/docs/assets/archkeel-hero.png" alt="Archkeel architecture gate and keel" width="600">
|
|
31
|
+
</p>
|
|
32
|
+
|
|
33
|
+

|
|
34
|
+
[](https://github.com/rapiddweller/archkeel/actions/workflows/ci.yml)
|
|
35
|
+
[](https://github.com/rapiddweller/archkeel/blob/main/LICENSE)
|
|
36
|
+
[](https://github.com/rapiddweller/archkeel/blob/main/docs/roadmap.md)
|
|
37
|
+
|
|
38
|
+
Archkeel checks architecture boundaries and declared changes in AI-assisted code.
|
|
39
|
+
It compares an accepted commit with a candidate, checks their scans against the
|
|
40
|
+
configured contract, and verifies that the candidate matches an expectation
|
|
41
|
+
published before its first submission.
|
|
42
|
+
|
|
43
|
+
It catches two failure modes that finding-only diffs miss:
|
|
44
|
+
|
|
45
|
+
- the architecture changed without being declared;
|
|
46
|
+
- the scanner saw less of the program, so the result looks clean only because
|
|
47
|
+
the graph became blinder.
|
|
48
|
+
|
|
49
|
+
[Quickstart](#quickstart) · [How it works](#how-it-works) ·
|
|
50
|
+
[Reference](https://github.com/rapiddweller/archkeel/blob/main/docs/reference.md) · [Roadmap](https://github.com/rapiddweller/archkeel/blob/main/docs/roadmap.md)
|
|
51
|
+
|
|
52
|
+
> [!NOTE]
|
|
53
|
+
> **Milestone 1:** `report` and `check` work. `accept` is still a placeholder.
|
|
54
|
+
> The Python analyzer ships inside the Archkeel package.
|
|
55
|
+
|
|
56
|
+
## Why Archkeel
|
|
57
|
+
|
|
58
|
+
An agent can keep tests green and introduce no new architecture finding while
|
|
59
|
+
making the code harder to analyze. If the gate compares finding identities
|
|
60
|
+
only, that change passes.
|
|
61
|
+
|
|
62
|
+
Fixture A is the smallest example:
|
|
63
|
+
|
|
64
|
+
```diff
|
|
65
|
+
def run(key: str) -> int:
|
|
66
|
+
- return first() + second()
|
|
67
|
+
+ handlers = {"first": first, "second": second}
|
|
68
|
+
+ return handlers[key]()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The refactor introduces no new forbidden import, cycle, or private crossing.
|
|
72
|
+
But static call resolution gets worse:
|
|
73
|
+
|
|
74
|
+
| Observation | Accepted | Candidate |
|
|
75
|
+
| --- | ---: | ---: |
|
|
76
|
+
| Resolved calls | 2 of 2 | 0 of 1 |
|
|
77
|
+
| Unresolved calls | 0 | 1 |
|
|
78
|
+
| New finding fingerprints | 0 | 0 |
|
|
79
|
+
| Archkeel verdict | baseline | **FAIL** |
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
expectation_fulfilled: FAIL
|
|
83
|
+
regression check failed in calls_unresolved: 0->1
|
|
84
|
+
regression check failed in unresolved_ratio: 0/2->1/1
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Archkeel compares raw measurements as well as finding counts and fingerprints.
|
|
88
|
+
The ratio check uses integer cross-multiplication, never rounded percentages:
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
U_candidate × T_accepted <= U_accepted × T_candidate (when both T > 0)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### What the gate adds
|
|
95
|
+
|
|
96
|
+
- **Precommitment with evidence.** The agent publishes the intended change
|
|
97
|
+
before it submits the candidate. Git ancestry and host records prove the
|
|
98
|
+
order; author timestamps do not.
|
|
99
|
+
- **Coverage-aware regression checks.** A disappearing edge is not mistaken
|
|
100
|
+
for an improvement just because a finding disappeared with it.
|
|
101
|
+
- **Explicit uncertainty.** An incomplete scan, broken lock, empty scope, or
|
|
102
|
+
runtime mismatch returns exit `2` with a diagnostic. Unknown never becomes
|
|
103
|
+
green.
|
|
104
|
+
|
|
105
|
+
Archkeel complements tests, linters, and human review. It does not replace any
|
|
106
|
+
of them. Its job is narrower: keep architecture changes declared, observable,
|
|
107
|
+
and mechanically checkable.
|
|
108
|
+
|
|
109
|
+
## Review surface
|
|
110
|
+
|
|
111
|
+
<p>
|
|
112
|
+
<img src="https://raw.githubusercontent.com/rapiddweller/archkeel/main/docs/assets/archkeel-report-preview.png" alt="Archkeel report showing the decision and three independent verdicts" width="1100">
|
|
113
|
+
</p>
|
|
114
|
+
|
|
115
|
+
The HTML report is designed for a reviewer making a merge decision:
|
|
116
|
+
|
|
117
|
+
- **Decision first.** `PASS`, `REJECT`, or `UNVERIFIABLE` is visible before details.
|
|
118
|
+
- **No blended score.** Scan completeness, contract compliance, and expectation matching
|
|
119
|
+
remain separate verdicts.
|
|
120
|
+
- **Unknown stays visible.** Missing or invalid evidence includes the affected subject,
|
|
121
|
+
unknown claim, and remedy.
|
|
122
|
+
- **Evidence stays inspectable.** Exact counts, fingerprints, source locations, digests,
|
|
123
|
+
and runtime provenance remain available beside the verdict.
|
|
124
|
+
|
|
125
|
+
## Quickstart
|
|
126
|
+
|
|
127
|
+
### Requirements
|
|
128
|
+
|
|
129
|
+
- Python 3.11+
|
|
130
|
+
|
|
131
|
+
Install from a checkout until the first Archkeel release on PyPI
|
|
132
|
+
(0.1.0 was published as `codekeel`):
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
uv sync --locked
|
|
136
|
+
uv run archkeel --help
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Add `archkeel.toml` to the repository you want to check:
|
|
140
|
+
|
|
141
|
+
```toml
|
|
142
|
+
[scan]
|
|
143
|
+
roots = ["src/example"] # directories, not globs
|
|
144
|
+
namespace = "example"
|
|
145
|
+
contract = "architecture-contract.json"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Observe the current repository:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
archkeel report \
|
|
152
|
+
--root /repo \
|
|
153
|
+
--output architecture.json
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The command also writes a self-contained `interactive.html` beside the canonical JSON.
|
|
157
|
+
It presents the three independent verdicts, exact measurements, diagnostics and provenance.
|
|
158
|
+
|
|
159
|
+
Check a candidate against its published expectation:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
archkeel check \
|
|
163
|
+
--root /repo \
|
|
164
|
+
--baseline "$B" \
|
|
165
|
+
--expectation-commit "$E" \
|
|
166
|
+
--head "$H" \
|
|
167
|
+
--expected expectation.json \
|
|
168
|
+
--expected-digest "$DIGEST" \
|
|
169
|
+
--accepted-branch main \
|
|
170
|
+
--branch candidate
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Run the Python version required by the repository being scanned. A mismatch is
|
|
174
|
+
reported as `runtime_mismatch` with exit `2`, not as broken source code.
|
|
175
|
+
|
|
176
|
+
## How it works
|
|
177
|
+
|
|
178
|
+
```mermaid
|
|
179
|
+
flowchart TB
|
|
180
|
+
B["Locked accepted state"] --> O["Observe accepted + candidate"]
|
|
181
|
+
E["Expectation published first"] --> H["Candidate submitted"]
|
|
182
|
+
H --> O
|
|
183
|
+
O --> C{"Deterministic check"}
|
|
184
|
+
C --> P["0 · pass"]
|
|
185
|
+
C --> R["1 · reject"]
|
|
186
|
+
C --> U["2 · unverifiable"]
|
|
187
|
+
|
|
188
|
+
classDef locked fill:#141414,stroke:#C5F82A,color:#E8E8E2
|
|
189
|
+
classDef declared fill:#141414,stroke:#5EEAD4,color:#E8E8E2
|
|
190
|
+
classDef candidate fill:#141414,stroke:#8A8A84,color:#E8E8E2
|
|
191
|
+
classDef gate fill:#C5F82A,stroke:#C5F82A,color:#0D1F05
|
|
192
|
+
classDef result fill:#141414,stroke:#2A2A28,color:#E8E8E2
|
|
193
|
+
|
|
194
|
+
class B locked
|
|
195
|
+
class E declared
|
|
196
|
+
class H,O candidate
|
|
197
|
+
class C gate
|
|
198
|
+
class P,R,U result
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
A check answers three independent questions. It never compresses them into a
|
|
202
|
+
single score.
|
|
203
|
+
|
|
204
|
+
| Verdict | Question | Typical failure |
|
|
205
|
+
| --- | --- | --- |
|
|
206
|
+
| `observation_complete` | Did the scan see everything it claims to see? | Incomplete scan, empty scope, rule without subjects |
|
|
207
|
+
| `declared_rules` | Does the code obey the architecture contract? | Forbidden import between components |
|
|
208
|
+
| `expectation_fulfilled` | Did the candidate match the declaration without regressions? | Coverage regression, undeclared change, late expectation |
|
|
209
|
+
|
|
210
|
+
### Exit codes
|
|
211
|
+
|
|
212
|
+
| Exit | Meaning |
|
|
213
|
+
| ---: | --- |
|
|
214
|
+
| `0` | Complete report or successful check |
|
|
215
|
+
| `1` | Rejected because at least one verdict is `FAIL` |
|
|
216
|
+
| `2` | Unverifiable input, always with at least one diagnostic |
|
|
217
|
+
|
|
218
|
+
Every exit `2` diagnostic contains:
|
|
219
|
+
|
|
220
|
+
```text
|
|
221
|
+
kind · subject · unknown_claim · remedy
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
A broken lock is therefore not interpreted as an empty accepted state.
|
|
225
|
+
|
|
226
|
+
## The M → B → E → H protocol
|
|
227
|
+
|
|
228
|
+
```mermaid
|
|
229
|
+
gitGraph
|
|
230
|
+
commit id: "M · accepted"
|
|
231
|
+
commit id: "B · lock only"
|
|
232
|
+
branch candidate
|
|
233
|
+
commit id: "E · expectation only"
|
|
234
|
+
commit id: "H · implementation"
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
| Commit | Contract |
|
|
238
|
+
| --- | --- |
|
|
239
|
+
| **M** | Accepted state. Archkeel re-observes it. |
|
|
240
|
+
| **B** | Lock-only child of M and tip of the accepted branch. It binds the config, checker, and observation digests. |
|
|
241
|
+
| **E** | Child of B that changes only the expectation file. It must be published before the first submission of H. |
|
|
242
|
+
| **H** | Descendant of E. It must not modify the lock, config, architecture contract, or expectation. |
|
|
243
|
+
|
|
244
|
+
### Agent workflow
|
|
245
|
+
|
|
246
|
+
1. Start from the lock commit **B**.
|
|
247
|
+
2. Write the intended architecture change and commit it alone as **E**.
|
|
248
|
+
3. Publish **E** before submitting implementation work.
|
|
249
|
+
4. Implement the change in one or more commits ending at **H**.
|
|
250
|
+
5. Run `archkeel check`. Fix the code or revise the proposal in a new protocol
|
|
251
|
+
cycle; do not rewrite protected inputs inside H.
|
|
252
|
+
|
|
253
|
+
Fixture B writes its expectation after implementation by deriving it from the
|
|
254
|
+
observed delta. Its architecture findings are otherwise clean. Archkeel still
|
|
255
|
+
rejects it:
|
|
256
|
+
|
|
257
|
+
```text
|
|
258
|
+
host_order: FAIL
|
|
259
|
+
expectation_fulfilled: FAIL
|
|
260
|
+
expectation was not published before the first candidate submission
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Precommitment proves "published before submission." It does not prove that no
|
|
264
|
+
private edit existed before publication.
|
|
265
|
+
|
|
266
|
+
## Host evidence
|
|
267
|
+
|
|
268
|
+
In GitLab CI, Archkeel reads merge-request diff versions through `glab` to
|
|
269
|
+
establish publication order.
|
|
270
|
+
|
|
271
|
+
For local testing, replay captured host records:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
uv run archkeel check ... --host-records records.json
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
A local replay validates the record shape and behavior. It does not prove host
|
|
278
|
+
authenticity.
|
|
279
|
+
|
|
280
|
+
## Development
|
|
281
|
+
|
|
282
|
+
Run the complete project gate:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
make check
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
This runs Ruff, strict mypy, pytest, and Archkeel's self-check.
|
|
289
|
+
|
|
290
|
+
Run the full release check, build both distributions, and install each one in isolation:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
make release-check
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Reproduce the protocol fixtures:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
make fixtures
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Archkeel checks its own boundaries. `archkeel.toml` and
|
|
303
|
+
[architecture-contract.json](https://github.com/rapiddweller/archkeel/blob/main/architecture-contract.json) define the contract;
|
|
304
|
+
[fixtures/D-self/result.json](https://github.com/rapiddweller/archkeel/blob/main/fixtures/D-self/result.json) contains the latest
|
|
305
|
+
self-scan.
|
|
306
|
+
|
|
307
|
+
```mermaid
|
|
308
|
+
flowchart TB
|
|
309
|
+
CLI["cli"] --> CHECK["check"]
|
|
310
|
+
CLI --> ACCEPT["accept"]
|
|
311
|
+
CHECK --> IR["ir"]
|
|
312
|
+
CHECK --> PRODUCER["analyzer"]
|
|
313
|
+
CHECK --> HOST["host"]
|
|
314
|
+
ACCEPT --> IR
|
|
315
|
+
IR --> RULE["imports nothing from archkeel"]
|
|
316
|
+
|
|
317
|
+
classDef module fill:#141414,stroke:#5EEAD4,color:#E8E8E2
|
|
318
|
+
classDef core fill:#141414,stroke:#C5F82A,color:#E8E8E2
|
|
319
|
+
classDef invariant fill:#C5F82A,stroke:#C5F82A,color:#0D1F05
|
|
320
|
+
|
|
321
|
+
class CLI,CHECK,ACCEPT,PRODUCER,HOST module
|
|
322
|
+
class IR core
|
|
323
|
+
class RULE invariant
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Current boundaries
|
|
327
|
+
|
|
328
|
+
Archkeel is deliberately strict about what it can prove:
|
|
329
|
+
|
|
330
|
+
- **Competing implementations:** review is still required when no declared rule
|
|
331
|
+
or observed regression exposes them.
|
|
332
|
+
- **Private crossings:** only import records are checked. `import pkg;
|
|
333
|
+
pkg._member` is not detected.
|
|
334
|
+
- **Precommitment:** publication order is proven; private editing order is not.
|
|
335
|
+
- **Analyzer runtime:** Archkeel's Python must be at least the target
|
|
336
|
+
repository's Python.
|
|
337
|
+
- **Acceptance:** `accept` is a placeholder and returns exit `2`.
|
|
338
|
+
|
|
339
|
+
## Roadmap
|
|
340
|
+
|
|
341
|
+
Milestone 1 delivers `report` and `check`. Next:
|
|
342
|
+
|
|
343
|
+
1. CI-only `accept`
|
|
344
|
+
2. a review page
|
|
345
|
+
3. agent commands: `propose` and `next`
|
|
346
|
+
|
|
347
|
+
See [docs/roadmap.md](https://github.com/rapiddweller/archkeel/blob/main/docs/roadmap.md) for sequencing and
|
|
348
|
+
[docs/reference.md](https://github.com/rapiddweller/archkeel/blob/main/docs/reference.md) for lock, host-record, schema, and
|
|
349
|
+
regression-check details.
|
|
350
|
+
|
|
351
|
+
## License
|
|
352
|
+
|
|
353
|
+
MIT © 2026 Rapiddweller Asia Co., Ltd.
|
|
354
|
+
|
|
355
|
+
Maintained by [Alexander Kell](https://github.com/ake2l).
|