hakodesh 0.2.2__tar.gz → 0.2.3__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.
- hakodesh-0.2.3/PKG-INFO +126 -0
- hakodesh-0.2.3/README.md +100 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/docs/IMPLEMENTATION.md +6 -6
- {hakodesh-0.2.2 → hakodesh-0.2.3}/docs/MIGRATION.md +19 -4
- {hakodesh-0.2.2 → hakodesh-0.2.3}/docs/PROCEDURAL_MEMORY.md +13 -13
- {hakodesh-0.2.2 → hakodesh-0.2.3}/docs/PROTOCOL.md +1 -1
- {hakodesh-0.2.2 → hakodesh-0.2.3}/pyproject.toml +2 -1
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/__init__.py +1 -1
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/catalog.py +46 -22
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/cli.py +24 -10
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/dispatch.py +2 -2
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/grimoire.py +13 -1
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/__init__.py +1 -1
- hakodesh-0.2.3/src/hakodesh.egg-info/PKG-INFO +126 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh.egg-info/SOURCES.txt +1 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh.egg-info/entry_points.txt +1 -0
- hakodesh-0.2.3/tests/test_cli_names.py +128 -0
- hakodesh-0.2.2/PKG-INFO +0 -100
- hakodesh-0.2.2/README.md +0 -74
- hakodesh-0.2.2/src/hakodesh.egg-info/PKG-INFO +0 -100
- {hakodesh-0.2.2 → hakodesh-0.2.3}/LICENSE +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/MANIFEST.in +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/docs/EXTRACT.md +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/setup.cfg +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/__main__.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/akashic.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/benchmark.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/combo.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/contracts/hakodesh-event-v1.json +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/enchant.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/events.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/home.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/keys.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/adapter.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/decide.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/execute.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/lifecycle.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/metrics.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/normalize.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/policy.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/procedures.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/promote.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/recall.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/risk.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/scope.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/memory/traces.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/mint.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/templates/combo.json.tmpl +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/templates/enchantment.json.tmpl +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/templates/spell.py.tmpl +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/templates/ward.json.tmpl +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh/ward.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh.egg-info/dependency_links.txt +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh.egg-info/requires.txt +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/src/hakodesh.egg-info/top_level.txt +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/tests/test_agnostic.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/tests/test_empty_book.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/tests/test_events.py +0 -0
- {hakodesh-0.2.2 → hakodesh-0.2.3}/tests/test_procedural_memory.py +0 -0
hakodesh-0.2.3/PKG-INFO
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hakodesh
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: Host-agnostic empty book with a deterministic procedural-memory runtime.
|
|
5
|
+
Author: Shelleyguitar
|
|
6
|
+
License-Expression: LicenseRef-Proprietary
|
|
7
|
+
Project-URL: Homepage, https://pypi.org/project/hakodesh/
|
|
8
|
+
Keywords: cli,sdk,spells,agents,receipts,akashic,grimoire
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: platformdirs<5,>=4.2
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
23
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
24
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# hakodesh
|
|
28
|
+
|
|
29
|
+
Host-agnostic Python CLI and SDK. After `pip install hakodesh` the user book is empty. Your LLM or agents **mint** spells, enchantments, wards, and combos as they need them. Repeated structured workflows can be **remembered** and, after a configurable promotion policy, executed as deterministic procedures **without another LLM pass**.
|
|
30
|
+
|
|
31
|
+
PyPI name and import: **hakodesh**. The command you type is **devra** — that is the `snx` role: `devra <spell> [args...]` casts a minted spell. `hakodesh` is the same CLI binary.
|
|
32
|
+
|
|
33
|
+
This package does **not** prove SNX token savings. Measurements are recall, correctness, straight-through execution, re-entry, model turns, and host-reported context crossing.
|
|
34
|
+
|
|
35
|
+
## Release
|
|
36
|
+
|
|
37
|
+
Current PyPI version is **0.2.3**. `pip install hakodesh` installs this release. The command you type is **devra**.
|
|
38
|
+
|
|
39
|
+
**0.2.0 and 0.2.1 were withdrawn** from the index (deleted, not yanked). 0.2.0's procedure integrity did not cover approval or routing state and parameterized replay reused last-seen literals. **0.1.0 remains** installable. **0.2.2 remains** as the previous current. 0.2.3 is the same runtime as 0.2.2; it teaches `devra` (the `snx` role), `spellbook`, and first-class `enchant` / `ward` / `combo`.
|
|
40
|
+
|
|
41
|
+
Procedures are HMAC-authenticated with the home chain key. Arguments that vary across training traces become required slots; `decide` / `run` take `--bind name=value`. Unsigned 0.2.0 `vN.json` files fail closed until re-promoted.
|
|
42
|
+
|
|
43
|
+
## Install
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install hakodesh
|
|
47
|
+
devra hello
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Data home: `HAKODESH_HOME` or the platform user-data directory for `hakodesh`. Never `~/spells`.
|
|
51
|
+
|
|
52
|
+
## Kernel commands
|
|
53
|
+
|
|
54
|
+
These are the runtime, not starter spells. Minted spell names are **kebab-case**. Kernel verbs are single tokens (`devra`, `spellbook`, `run`). Two-word leftovers stay kebab as aliases (`grimoire-seal`, `run-intent`, `next-action`).
|
|
55
|
+
|
|
56
|
+
### Cast
|
|
57
|
+
|
|
58
|
+
| Command | What it does |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `devra <spell> [args...]` | Cast a minted spell. Same job `snx <spell>` has on Magus. Alias: `hakodesh devra …` / `invoke` |
|
|
61
|
+
|
|
62
|
+
### Spellbook
|
|
63
|
+
|
|
64
|
+
| Command | What it does |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `devra mint <name> --kind spell\|enchantment\|ward\|combo` | Scaffold into the spellbook (preview; `--confirm` writes) |
|
|
67
|
+
| `devra spellbook` | List user artifacts (empty at install). Aliases: `catalog`, `book` |
|
|
68
|
+
| `devra route "<intent>"` | Rank minted names plus kernel commands (may include procedure candidates) |
|
|
69
|
+
|
|
70
|
+
### Kinds — enchantments, wards, combos
|
|
71
|
+
|
|
72
|
+
These were never gone. They are first-class kernel commands:
|
|
73
|
+
|
|
74
|
+
| Command | What it does |
|
|
75
|
+
|---|---|
|
|
76
|
+
| `devra enchant bind\|lift <name> --settings <path>` | Bind or lift a minted **enchantment** |
|
|
77
|
+
| `devra ward status\|lock\|unlock\|check <name>` | Fail-closed **ward** |
|
|
78
|
+
| `devra combo seal\|cast\|list [name]` | Sealed **combo** pipelines of minted spells |
|
|
79
|
+
|
|
80
|
+
### Memory
|
|
81
|
+
|
|
82
|
+
| Command | What it does |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `devra remember --intent "…" --step spell:name --source host` | Record a structured execution trace (not an opaque receipt) |
|
|
85
|
+
| `devra recall "<intent>"` | Local deterministic procedure recall |
|
|
86
|
+
| `devra decide "<intent>" [--bind name=value]` | `execute` / `ask_model` / `ambiguous` / `blocked` / `not_found` |
|
|
87
|
+
| `devra run "<intent>" [--bind name=value]` | Straight-through execute when decide says `execute`. Alias: `run-intent` |
|
|
88
|
+
| `devra next --intent "…" [--bind name=value]` | Next validated procedure step, or a suggestion. Alias: `next-action` |
|
|
89
|
+
| `devra rites` | List promoted procedures. Alias: `procedures` |
|
|
90
|
+
| `devra approve <id> --confirm` | Approve a high-risk procedure |
|
|
91
|
+
| `devra promote [--replace]` | Run promotion now (remember already tries after each success) |
|
|
92
|
+
| `devra policy` | Show promotion policy (three-success default is an implementation policy, not SNX history) |
|
|
93
|
+
| `devra metrics` | Recall / straight-through / re-entry / context-crossing stats |
|
|
94
|
+
| `devra benchmark` | Isolated tempfile-home bench (not the operator home) |
|
|
95
|
+
|
|
96
|
+
### Ledger
|
|
97
|
+
|
|
98
|
+
| Command | What it does |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `devra akashic` | Verify HMAC chain; `--tail N` |
|
|
101
|
+
| `devra grimoire` | Cast ledger stats. `grimoire seal --confirm` writes the Merkle seal; `grimoire verify` checks it. Alias: `grimoire-seal` |
|
|
102
|
+
| `devra protocol` | Print the `hakodesh.event/v1` contract descriptor |
|
|
103
|
+
|
|
104
|
+
`--like` on an empty book uses the **kind template** in the wheel. After one spell exists, `--like <that>` copies its shape.
|
|
105
|
+
|
|
106
|
+
Every mint and cast emits `hakodesh.event/v1`. Akashic is SHA-256 linked and HMAC-SHA256 signed. Grimoire is Merkle-sealed with the same chain key. Promoted procedures use that same home key for `procedure_mac`. The keystore is `$HAKODESH_HOME/keys` (0700/0600), minted on first seal, never in the wheel.
|
|
107
|
+
|
|
108
|
+
Notifications default to `none`. The package does not write LaunchAgents or editor hooks until you mint and bind an enchantment.
|
|
109
|
+
|
|
110
|
+
## SDK
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from hakodesh.catalog import catalog
|
|
114
|
+
from hakodesh.mint import mint
|
|
115
|
+
from hakodesh import events, akashic, grimoire
|
|
116
|
+
from hakodesh.enchant import bind, lift
|
|
117
|
+
from hakodesh.ward import unlock
|
|
118
|
+
from hakodesh.combo import seal, cast
|
|
119
|
+
from hakodesh.memory import remember, recall, decide, run_intent, next_action, approve
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
See `docs/PROCEDURAL_MEMORY.md` and `docs/MIGRATION.md`.
|
|
123
|
+
|
|
124
|
+
## Empty book law
|
|
125
|
+
|
|
126
|
+
A fresh install has zero user spells, enchantments, wards, combos, or promoted procedures. Discovery picks up a file the moment it lands under `HAKODESH_HOME/book/`.
|
hakodesh-0.2.3/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# hakodesh
|
|
2
|
+
|
|
3
|
+
Host-agnostic Python CLI and SDK. After `pip install hakodesh` the user book is empty. Your LLM or agents **mint** spells, enchantments, wards, and combos as they need them. Repeated structured workflows can be **remembered** and, after a configurable promotion policy, executed as deterministic procedures **without another LLM pass**.
|
|
4
|
+
|
|
5
|
+
PyPI name and import: **hakodesh**. The command you type is **devra** — that is the `snx` role: `devra <spell> [args...]` casts a minted spell. `hakodesh` is the same CLI binary.
|
|
6
|
+
|
|
7
|
+
This package does **not** prove SNX token savings. Measurements are recall, correctness, straight-through execution, re-entry, model turns, and host-reported context crossing.
|
|
8
|
+
|
|
9
|
+
## Release
|
|
10
|
+
|
|
11
|
+
Current PyPI version is **0.2.3**. `pip install hakodesh` installs this release. The command you type is **devra**.
|
|
12
|
+
|
|
13
|
+
**0.2.0 and 0.2.1 were withdrawn** from the index (deleted, not yanked). 0.2.0's procedure integrity did not cover approval or routing state and parameterized replay reused last-seen literals. **0.1.0 remains** installable. **0.2.2 remains** as the previous current. 0.2.3 is the same runtime as 0.2.2; it teaches `devra` (the `snx` role), `spellbook`, and first-class `enchant` / `ward` / `combo`.
|
|
14
|
+
|
|
15
|
+
Procedures are HMAC-authenticated with the home chain key. Arguments that vary across training traces become required slots; `decide` / `run` take `--bind name=value`. Unsigned 0.2.0 `vN.json` files fail closed until re-promoted.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install hakodesh
|
|
21
|
+
devra hello
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Data home: `HAKODESH_HOME` or the platform user-data directory for `hakodesh`. Never `~/spells`.
|
|
25
|
+
|
|
26
|
+
## Kernel commands
|
|
27
|
+
|
|
28
|
+
These are the runtime, not starter spells. Minted spell names are **kebab-case**. Kernel verbs are single tokens (`devra`, `spellbook`, `run`). Two-word leftovers stay kebab as aliases (`grimoire-seal`, `run-intent`, `next-action`).
|
|
29
|
+
|
|
30
|
+
### Cast
|
|
31
|
+
|
|
32
|
+
| Command | What it does |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `devra <spell> [args...]` | Cast a minted spell. Same job `snx <spell>` has on Magus. Alias: `hakodesh devra …` / `invoke` |
|
|
35
|
+
|
|
36
|
+
### Spellbook
|
|
37
|
+
|
|
38
|
+
| Command | What it does |
|
|
39
|
+
|---|---|
|
|
40
|
+
| `devra mint <name> --kind spell\|enchantment\|ward\|combo` | Scaffold into the spellbook (preview; `--confirm` writes) |
|
|
41
|
+
| `devra spellbook` | List user artifacts (empty at install). Aliases: `catalog`, `book` |
|
|
42
|
+
| `devra route "<intent>"` | Rank minted names plus kernel commands (may include procedure candidates) |
|
|
43
|
+
|
|
44
|
+
### Kinds — enchantments, wards, combos
|
|
45
|
+
|
|
46
|
+
These were never gone. They are first-class kernel commands:
|
|
47
|
+
|
|
48
|
+
| Command | What it does |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `devra enchant bind\|lift <name> --settings <path>` | Bind or lift a minted **enchantment** |
|
|
51
|
+
| `devra ward status\|lock\|unlock\|check <name>` | Fail-closed **ward** |
|
|
52
|
+
| `devra combo seal\|cast\|list [name]` | Sealed **combo** pipelines of minted spells |
|
|
53
|
+
|
|
54
|
+
### Memory
|
|
55
|
+
|
|
56
|
+
| Command | What it does |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `devra remember --intent "…" --step spell:name --source host` | Record a structured execution trace (not an opaque receipt) |
|
|
59
|
+
| `devra recall "<intent>"` | Local deterministic procedure recall |
|
|
60
|
+
| `devra decide "<intent>" [--bind name=value]` | `execute` / `ask_model` / `ambiguous` / `blocked` / `not_found` |
|
|
61
|
+
| `devra run "<intent>" [--bind name=value]` | Straight-through execute when decide says `execute`. Alias: `run-intent` |
|
|
62
|
+
| `devra next --intent "…" [--bind name=value]` | Next validated procedure step, or a suggestion. Alias: `next-action` |
|
|
63
|
+
| `devra rites` | List promoted procedures. Alias: `procedures` |
|
|
64
|
+
| `devra approve <id> --confirm` | Approve a high-risk procedure |
|
|
65
|
+
| `devra promote [--replace]` | Run promotion now (remember already tries after each success) |
|
|
66
|
+
| `devra policy` | Show promotion policy (three-success default is an implementation policy, not SNX history) |
|
|
67
|
+
| `devra metrics` | Recall / straight-through / re-entry / context-crossing stats |
|
|
68
|
+
| `devra benchmark` | Isolated tempfile-home bench (not the operator home) |
|
|
69
|
+
|
|
70
|
+
### Ledger
|
|
71
|
+
|
|
72
|
+
| Command | What it does |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `devra akashic` | Verify HMAC chain; `--tail N` |
|
|
75
|
+
| `devra grimoire` | Cast ledger stats. `grimoire seal --confirm` writes the Merkle seal; `grimoire verify` checks it. Alias: `grimoire-seal` |
|
|
76
|
+
| `devra protocol` | Print the `hakodesh.event/v1` contract descriptor |
|
|
77
|
+
|
|
78
|
+
`--like` on an empty book uses the **kind template** in the wheel. After one spell exists, `--like <that>` copies its shape.
|
|
79
|
+
|
|
80
|
+
Every mint and cast emits `hakodesh.event/v1`. Akashic is SHA-256 linked and HMAC-SHA256 signed. Grimoire is Merkle-sealed with the same chain key. Promoted procedures use that same home key for `procedure_mac`. The keystore is `$HAKODESH_HOME/keys` (0700/0600), minted on first seal, never in the wheel.
|
|
81
|
+
|
|
82
|
+
Notifications default to `none`. The package does not write LaunchAgents or editor hooks until you mint and bind an enchantment.
|
|
83
|
+
|
|
84
|
+
## SDK
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from hakodesh.catalog import catalog
|
|
88
|
+
from hakodesh.mint import mint
|
|
89
|
+
from hakodesh import events, akashic, grimoire
|
|
90
|
+
from hakodesh.enchant import bind, lift
|
|
91
|
+
from hakodesh.ward import unlock
|
|
92
|
+
from hakodesh.combo import seal, cast
|
|
93
|
+
from hakodesh.memory import remember, recall, decide, run_intent, next_action, approve
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
See `docs/PROCEDURAL_MEMORY.md` and `docs/MIGRATION.md`.
|
|
97
|
+
|
|
98
|
+
## Empty book law
|
|
99
|
+
|
|
100
|
+
A fresh install has zero user spells, enchantments, wards, combos, or promoted procedures. Discovery picks up a file the moment it lands under `HAKODESH_HOME/book/`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Hakodesh 0.2.
|
|
1
|
+
# Hakodesh 0.2.3 — procedural memory implementation report
|
|
2
2
|
|
|
3
3
|
This implementation does **not** prove SNX token savings. Tests and measurements establish local recall, promotion, straight-through execution, fail-closed safety, and host-reported context accounting only.
|
|
4
4
|
|
|
@@ -10,14 +10,14 @@ Public 0.2.0 needed correction. 0.2.1 ships:
|
|
|
10
10
|
|---|---|
|
|
11
11
|
| HKD-020-001 | HMAC-SHA256 `procedure_mac` over the full authenticated body including `risk.approved`; `approve()` writes `vN+1` and emits `procedure.approved` |
|
|
12
12
|
| HKD-020-002 | `intent_example`, `normalized_intent`, tags, aliases, and status are in the authenticated body |
|
|
13
|
-
| HKD-020-003 | Varying training args become required slots; `run
|
|
13
|
+
| HKD-020-003 | Varying training args become required slots; `run --bind` / SDK `bindings=`; fail closed if missing |
|
|
14
14
|
| HKD-020-004 | Every success slice is searched; the latest clean cluster is promoted |
|
|
15
15
|
| HKD-020-005 | Promotion uses `_cluster_confidence` vs `min_confidence`; policy probabilities must be in `[0, 1]` |
|
|
16
16
|
| HKD-020-006 | Benchmark no longer double-counts `task_complete` on a successful replay |
|
|
17
17
|
| HKD-020-007 | `procedure.recorded`, `procedure.failed`, and `procedure.decision` are emitted |
|
|
18
18
|
| HKD-020-008 | 0.1.0 **sdist** sha256 `3e5959447bd1999797104a7fe27a3b6bc1253d2fb534d03809fbc7ed4ae91257`; **wheel** sha256 `7e74e20de8aa1af606299ae64d2fc01c89627dc405b668f159c957b1b23c8145` |
|
|
19
19
|
|
|
20
|
-
Public **0.2.0** needed that correction and was later withdrawn from the index. **0.2.2** is
|
|
20
|
+
Public **0.2.0** needed that correction and was later withdrawn from the index. **0.2.1** (the HMAC/`--bind` runtime) was also Chrome-deleted after **0.2.2** landed. **0.2.3** is that same runtime with `devra` / `spellbook` / kinds as the taught CLI: https://pypi.org/project/hakodesh/0.2.3/
|
|
21
21
|
|
|
22
22
|
## Files changed
|
|
23
23
|
|
|
@@ -34,14 +34,14 @@ Modified:
|
|
|
34
34
|
|
|
35
35
|
- `src/hakodesh/{cli,catalog,home,events,__init__}.py`
|
|
36
36
|
- `src/hakodesh/contracts/hakodesh-event-v1.json`
|
|
37
|
-
- `pyproject.toml` (0.2.
|
|
37
|
+
- `pyproject.toml` (0.2.3)
|
|
38
38
|
- `README.md`, `docs/PROTOCOL.md`
|
|
39
39
|
|
|
40
40
|
SNX was not modified.
|
|
41
41
|
|
|
42
42
|
## Architecture implemented
|
|
43
43
|
|
|
44
|
-
Structured host/agent/executor traces → configurable promotion → versioned hashed procedures → local recall (Jaccard + sequence + tags, no LLM/network) → `decide` → optional straight-through `run
|
|
44
|
+
Structured host/agent/executor traces → configurable promotion → versioned hashed procedures → local recall (Jaccard + sequence + tags, no LLM/network) → `decide` → optional straight-through `run` via existing `dispatch.invoke`. Compact receipts stay small; audit JSON stays on disk. Optional `ModelAdapter` exists for hosts and is never called by the executor.
|
|
45
45
|
|
|
46
46
|
## Promotion and time-window policy
|
|
47
47
|
|
|
@@ -57,7 +57,7 @@ Wards run at the execution boundary before `dispatch.invoke`. Procedure HMAC (ho
|
|
|
57
57
|
|
|
58
58
|
## Backward compatibility
|
|
59
59
|
|
|
60
|
-
`catalog`, `route` (richer keys), `mint` preview/`--confirm`, `
|
|
60
|
+
`spellbook` (aliases `catalog`, `book`), `route` (richer keys), `mint` preview/`--confirm`, `devra <spell>` to cast, `combo` / `ward` / `enchant`, existing events remain. Fresh install: zero user artifacts and zero procedures.
|
|
61
61
|
|
|
62
62
|
## Tests run and results
|
|
63
63
|
|
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
# Migration
|
|
2
2
|
|
|
3
|
+
## 0.2.2 → 0.2.3
|
|
4
|
+
|
|
5
|
+
0.2.3 does **not** change runtime behavior. It is the CLI-name release: **devra** is the caster (`snx` role), **spellbook** lists artifacts, and enchantments / wards / combos are first-class kinds. Old names remain aliases. Current install is **0.2.3**. **0.2.0 and 0.2.1 were withdrawn** (deleted, not yanked). **0.1.0 and 0.2.2 stay.**
|
|
6
|
+
|
|
7
|
+
| Old | Now |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `snx <spell>` / `invoke` / type the name | `devra <spell>` (package CLI alias: `hakodesh`) |
|
|
10
|
+
| `catalog` / `book` | `spellbook` |
|
|
11
|
+
| `run-intent` | `run` |
|
|
12
|
+
| `next-action` | `next` |
|
|
13
|
+
| `procedures` | `rites` |
|
|
14
|
+
| `grimoire-seal` / `grimoire-seal --verify` | `grimoire seal` / `grimoire verify` |
|
|
15
|
+
|
|
16
|
+
Nothing is hidden. Enchantments, wards, and combos are the `kinds` group: `enchant`, `ward`, `combo`. `promote`, `benchmark`, and `protocol` sit in memory/ledger.
|
|
17
|
+
|
|
3
18
|
## 0.2.1 → 0.2.2
|
|
4
19
|
|
|
5
|
-
0.2.2 does **not** change runtime behavior. It is the public-metadata release: README and shipped docs now match the live index. Current install is **0.2.2**. **0.2.0
|
|
20
|
+
0.2.2 does **not** change runtime behavior. It is the public-metadata release: README and shipped docs now match the live index. Current install is **0.2.2**. **0.2.0 and 0.2.1 were withdrawn** (deleted, not yanked). **0.1.0 stays.**
|
|
6
21
|
|
|
7
22
|
## 0.2.0 → 0.2.1
|
|
8
23
|
|
|
@@ -18,7 +33,7 @@
|
|
|
18
33
|
| Benchmark accounting | One `task_complete` per successful replay (execute already records it). |
|
|
19
34
|
| Lifecycle events | `procedure.recorded`, `procedure.failed`, `procedure.decision`, and `procedure.approved` are now emitted. |
|
|
20
35
|
|
|
21
|
-
**PyPI current is 0.2.
|
|
36
|
+
**PyPI current is 0.2.3:** https://pypi.org/project/hakodesh/0.2.3/ — 0.2.0 and 0.2.1 were withdrawn (deleted, not yanked). 0.1.0 and 0.2.2 stay on the index.
|
|
22
37
|
|
|
23
38
|
## 0.1.0 → 0.2.0
|
|
24
39
|
|
|
@@ -27,7 +42,7 @@ Hakodesh 0.2.0 is a compatibility-preserving extension. Existing 0.1.0 homes kee
|
|
|
27
42
|
## What stays the same
|
|
28
43
|
|
|
29
44
|
- Empty-book law: fresh install still has zero user spells, enchantments, wards, combos, **and** zero promoted procedures.
|
|
30
|
-
- `catalog`, `mint` (preview / `--confirm`), `
|
|
45
|
+
- `spellbook` (aliases `catalog`, `book`), `mint` (preview / `--confirm`), `devra <spell>` to cast, `combo`, Akashic HMAC chain, Grimoire Merkle seal, wards, enchant bind/lift.
|
|
31
46
|
- Existing `hakodesh.event/v1` lines remain readable. New kinds are additive.
|
|
32
47
|
- Data still lives under `HAKODESH_HOME`, never `~/spells`.
|
|
33
48
|
|
|
@@ -40,7 +55,7 @@ Hakodesh 0.2.0 is a compatibility-preserving extension. Existing 0.1.0 homes kee
|
|
|
40
55
|
| `$HAKODESH_HOME/memory/policy.json` | Promotion policy (created when saved) |
|
|
41
56
|
| `$HAKODESH_HOME/memory/metrics.jsonl` | Recall / decide / execute instrumentation |
|
|
42
57
|
|
|
43
|
-
New kernel commands: `remember`, `recall`, `decide`, `run-intent
|
|
58
|
+
New kernel commands: `remember`, `recall`, `decide`, `run` (alias `run-intent`), `next` (alias `next-action`), `rites` (alias `procedures`), `approve`, `metrics`, `policy`, `promote`, `benchmark`, `protocol`. Cast is `devra`. Artifact list is `spellbook`. `grimoire seal` / `grimoire verify` replace `grimoire-seal` as the taught form.
|
|
44
59
|
|
|
45
60
|
`route` still returns `matches`. It may also include `procedures` and `decision_hint`.
|
|
46
61
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Procedural memory
|
|
2
2
|
|
|
3
|
-
Hakodesh 0.2.
|
|
3
|
+
Hakodesh 0.2.3 ships a **deterministic procedural-memory runtime** (same behavior as 0.2.2 / 0.2.1). It does not use an LLM, embeddings service, or network call on the default recall / decide / execute path.
|
|
4
4
|
|
|
5
5
|
This is not a claim about SNX token savings. The three-success promotion default is an **implementation policy**, not evidence about SNX's historical rule.
|
|
6
6
|
|
|
@@ -24,7 +24,7 @@ host/agent structured trace
|
|
|
24
24
|
▼
|
|
25
25
|
decide() ── execute | ask_model | ambiguous | blocked | not_found
|
|
26
26
|
│
|
|
27
|
-
├── execute ──► run
|
|
27
|
+
├── execute ──► run: ward + HMAC + scope + approval + bindings, then dispatch.invoke
|
|
28
28
|
│ compact receipt; audit on disk
|
|
29
29
|
└── otherwise ──► needs_model_reasoning; no speculative recovery
|
|
30
30
|
```
|
|
@@ -51,7 +51,7 @@ Low-confidence and ambiguous matches never execute automatically.
|
|
|
51
51
|
| Crosses into a model | Stays local |
|
|
52
52
|
|---|---|
|
|
53
53
|
| Host-reported `model_crossed_bytes` / `billed_tokens` / `model_turns` | traces, procedures, receipts, Akashic, Grimoire, metrics.jsonl, compact CLI JSON |
|
|
54
|
-
| Optional host `ModelAdapter.reason` after `needs_model_reasoning` | straight-through `run
|
|
54
|
+
| Optional host `ModelAdapter.reason` after `needs_model_reasoning` | straight-through `run` |
|
|
55
55
|
|
|
56
56
|
The executor never instantiates a model adapter. Receipt **size** is not a proxy for reasoning avoided.
|
|
57
57
|
|
|
@@ -83,16 +83,16 @@ Visible on every promotion receipt and `hakodesh policy`.
|
|
|
83
83
|
## CLI
|
|
84
84
|
|
|
85
85
|
```
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
86
|
+
devra remember --intent "…" --step spell:name[:arg] --source host --outcome success
|
|
87
|
+
devra recall "…"
|
|
88
|
+
devra decide "…" [--bind name=value]
|
|
89
|
+
devra run "…" [--bind name=value]
|
|
90
|
+
devra next --intent "…" [--bind name=value]
|
|
91
|
+
devra rites
|
|
92
|
+
devra approve proc_… --confirm
|
|
93
|
+
devra policy
|
|
94
|
+
devra metrics
|
|
95
|
+
devra benchmark
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
## SDK
|
|
@@ -34,7 +34,7 @@ Key: `$HAKODESH_HOME/keys/akashic-chain-hmac` (dir 0700, file 0600), minted on f
|
|
|
34
34
|
|
|
35
35
|
## Grimoire Merkle seal
|
|
36
36
|
|
|
37
|
-
`HAKODESH_HOME/grimoire.jsonl` is the cast ledger. `grimoire
|
|
37
|
+
`HAKODESH_HOME/grimoire.jsonl` is the cast ledger. `grimoire seal` builds RFC 6962 trees (leaf prefix `0x00`, node prefix `0x01`): per-day batch roots, then a master root over `day + 0x1f + day_root` leaves. Head MAC: `HMAC(grimoire-merkle:{root}:{lines}:{key_fp})` with the Akashic chain key. `grimoire-seal` remains an alias.
|
|
38
38
|
|
|
39
39
|
## Mint lifecycle
|
|
40
40
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hakodesh"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "Host-agnostic empty book with a deterministic procedural-memory runtime."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -29,6 +29,7 @@ dev = ["pytest>=8.0", "build>=1.2", "twine>=5.0"]
|
|
|
29
29
|
|
|
30
30
|
[project.scripts]
|
|
31
31
|
hakodesh = "hakodesh.cli:main"
|
|
32
|
+
devra = "hakodesh.cli:main"
|
|
32
33
|
|
|
33
34
|
[project.urls]
|
|
34
35
|
Homepage = "https://pypi.org/project/hakodesh/"
|
|
@@ -11,7 +11,7 @@ from .grimoire import seal as grimoire_seal
|
|
|
11
11
|
from .memory import approve, decide, metrics_summary, next_action, recall, remember, run_intent
|
|
12
12
|
from .ward import unlock
|
|
13
13
|
|
|
14
|
-
__version__ = "0.2.
|
|
14
|
+
__version__ = "0.2.3"
|
|
15
15
|
__all__ = [
|
|
16
16
|
"list_catalog",
|
|
17
17
|
"route",
|
|
@@ -7,28 +7,45 @@ from pathlib import Path
|
|
|
7
7
|
|
|
8
8
|
from . import home as paths
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
|
|
10
|
+
# Advertised kernel — primary names only. Old names live in ALIASES and still dispatch.
|
|
11
|
+
# `devra` is the snx-shaped caster: `devra <spell> [args...]`.
|
|
12
|
+
# Minted spell names are kebab-case. Kernel verbs are single tokens unless they already were kebab aliases.
|
|
13
|
+
KERNEL_GROUPS = {
|
|
14
|
+
"cast": ("devra",),
|
|
15
|
+
"spellbook": ("mint", "spellbook", "route"),
|
|
16
|
+
"kinds": ("enchant", "ward", "combo"),
|
|
17
|
+
"memory": (
|
|
18
|
+
"remember",
|
|
19
|
+
"recall",
|
|
20
|
+
"decide",
|
|
21
|
+
"run",
|
|
22
|
+
"next",
|
|
23
|
+
"rites",
|
|
24
|
+
"approve",
|
|
25
|
+
"promote",
|
|
26
|
+
"policy",
|
|
27
|
+
"metrics",
|
|
28
|
+
"benchmark",
|
|
29
|
+
),
|
|
30
|
+
"ledger": ("akashic", "grimoire", "protocol"),
|
|
31
|
+
}
|
|
32
|
+
KERNEL = tuple(name for group in KERNEL_GROUPS.values() for name in group)
|
|
33
|
+
ALIASES = {
|
|
34
|
+
"catalog": "spellbook",
|
|
35
|
+
"book": "spellbook",
|
|
36
|
+
"invoke": "devra",
|
|
37
|
+
"run-intent": "run",
|
|
38
|
+
"run_intent": "run",
|
|
39
|
+
"next-action": "next",
|
|
40
|
+
"next_action": "next",
|
|
41
|
+
"procedures": "rites",
|
|
42
|
+
"grimoire-seal": "grimoire",
|
|
43
|
+
}
|
|
44
|
+
KINDS_DETAIL = {
|
|
45
|
+
"enchant": "enchantments — bind|lift <name> --settings PATH [--confirm]",
|
|
46
|
+
"ward": "wards — status|lock|unlock|check <name>",
|
|
47
|
+
"combo": "combos — seal|cast|list [name]",
|
|
48
|
+
}
|
|
32
49
|
|
|
33
50
|
|
|
34
51
|
def _load_spell(path: Path):
|
|
@@ -86,6 +103,9 @@ def catalog(root: Path | None = None):
|
|
|
86
103
|
for item in items
|
|
87
104
|
],
|
|
88
105
|
"kernel": list(KERNEL),
|
|
106
|
+
"groups": {key: list(names) for key, names in KERNEL_GROUPS.items()},
|
|
107
|
+
"aliases": dict(ALIASES),
|
|
108
|
+
"kinds": dict(KINDS_DETAIL),
|
|
89
109
|
}
|
|
90
110
|
|
|
91
111
|
|
|
@@ -97,6 +117,10 @@ def route(intent: str, root: Path | None = None):
|
|
|
97
117
|
intent = (intent or "").lower()
|
|
98
118
|
scored = []
|
|
99
119
|
haystacks = [(name, "kernel command %s" % name, "kernel") for name in KERNEL]
|
|
120
|
+
haystacks.extend(
|
|
121
|
+
(alias, "kernel command %s alias %s" % (alias, target), "kernel")
|
|
122
|
+
for alias, target in ALIASES.items()
|
|
123
|
+
)
|
|
100
124
|
for item in user_artifacts(root):
|
|
101
125
|
desc = item.get("descriptor") or {}
|
|
102
126
|
hay = "%s %s %s" % (item["name"], desc.get("purpose", ""), " ".join(desc.get("tags") or []))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""devra CLI — JSON in / JSON out. Package import remains hakodesh."""
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
import json
|
|
@@ -96,8 +96,13 @@ def main(argv=None) -> int:
|
|
|
96
96
|
if not argv or argv[0] in ("-h", "--help", "help"):
|
|
97
97
|
emit(
|
|
98
98
|
{
|
|
99
|
-
"usage": "
|
|
99
|
+
"usage": "devra <command> [args]",
|
|
100
|
+
"package": "hakodesh",
|
|
101
|
+
"cast": "devra <spell> [args...]",
|
|
102
|
+
"groups": {key: list(names) for key, names in catalog.KERNEL_GROUPS.items()},
|
|
103
|
+
"kinds": dict(catalog.KINDS_DETAIL),
|
|
100
104
|
"kernel": list(catalog.KERNEL),
|
|
105
|
+
"aliases": dict(catalog.ALIASES),
|
|
101
106
|
}
|
|
102
107
|
)
|
|
103
108
|
return 0
|
|
@@ -115,16 +120,16 @@ def main(argv=None) -> int:
|
|
|
115
120
|
|
|
116
121
|
def _dispatch(cmd, rest):
|
|
117
122
|
confirm = _has(rest, "--confirm")
|
|
118
|
-
if cmd
|
|
123
|
+
if cmd in {"spellbook", "book", "catalog"}:
|
|
119
124
|
return catalog.catalog()
|
|
120
125
|
if cmd == "route":
|
|
121
126
|
return catalog.route(" ".join(rest))
|
|
122
|
-
if cmd
|
|
127
|
+
if cmd in {"devra", "invoke"}:
|
|
123
128
|
if not rest:
|
|
124
|
-
return {"ok": False, "error": "usage:
|
|
129
|
+
return {"ok": False, "error": "usage: devra <spell> [args...]"}
|
|
125
130
|
if rest[0] == "--route":
|
|
126
131
|
return catalog.route(" ".join(rest[1:]))
|
|
127
|
-
if rest[0]
|
|
132
|
+
if rest[0] in {"--catalog", "--spellbook"}:
|
|
128
133
|
return catalog.catalog()
|
|
129
134
|
return dispatch.invoke(rest[0], rest[1:])
|
|
130
135
|
if cmd == "mint":
|
|
@@ -141,7 +146,16 @@ def _dispatch(cmd, rest):
|
|
|
141
146
|
return {"ok": True, "events": akashic.tail_events(n)}
|
|
142
147
|
return akashic.verify_chain(strict=_has(rest, "--strict"))
|
|
143
148
|
if cmd == "grimoire":
|
|
144
|
-
|
|
149
|
+
if _has(rest, "--verify"):
|
|
150
|
+
return grimoire.verify()
|
|
151
|
+
action = rest[0] if rest else "stats"
|
|
152
|
+
if action in {"stats", "status"}:
|
|
153
|
+
return grimoire.stats()
|
|
154
|
+
if action == "seal":
|
|
155
|
+
return grimoire.seal(confirm=confirm)
|
|
156
|
+
if action == "verify":
|
|
157
|
+
return grimoire.verify()
|
|
158
|
+
return {"ok": False, "error": "usage: grimoire [stats|seal|verify]"}
|
|
145
159
|
if cmd == "grimoire-seal":
|
|
146
160
|
if _has(rest, "--verify"):
|
|
147
161
|
return grimoire.verify()
|
|
@@ -287,14 +301,14 @@ def _memory_dispatch(cmd, rest, confirm):
|
|
|
287
301
|
if cmd == "decide":
|
|
288
302
|
bindings, leftover = _parse_bindings(rest)
|
|
289
303
|
return decide(" ".join(leftover), bindings=bindings or None)
|
|
290
|
-
if cmd in {"run-intent", "run_intent"}:
|
|
304
|
+
if cmd in {"run", "run-intent", "run_intent"}:
|
|
291
305
|
bindings, leftover = _parse_bindings(rest)
|
|
292
306
|
return run_intent(
|
|
293
307
|
" ".join(x for x in leftover if x != "--full"),
|
|
294
308
|
full=_has(rest, "--full"),
|
|
295
309
|
bindings=bindings or None,
|
|
296
310
|
)
|
|
297
|
-
if cmd in {"next-action", "next_action"}:
|
|
311
|
+
if cmd in {"next", "next-action", "next_action"}:
|
|
298
312
|
bindings, leftover = _parse_bindings(rest)
|
|
299
313
|
after = _flag(leftover, "--after-step")
|
|
300
314
|
intent = _flag(leftover, "--intent") or " ".join(
|
|
@@ -307,7 +321,7 @@ def _memory_dispatch(cmd, rest, confirm):
|
|
|
307
321
|
)
|
|
308
322
|
if cmd == "promote":
|
|
309
323
|
return promote_mod.maybe_promote(replace=_has(rest, "--replace"))
|
|
310
|
-
if cmd
|
|
324
|
+
if cmd in {"rites", "procedures"}:
|
|
311
325
|
rows = procedures_mod.list_procedures()
|
|
312
326
|
return {"ok": True, "count": len(rows), "procedures": rows}
|
|
313
327
|
if cmd == "approve":
|
|
@@ -8,8 +8,8 @@ from . import akashic, catalog, events, grimoire
|
|
|
8
8
|
|
|
9
9
|
def invoke(name: str, args=None, *, surface="cli", root=None) -> dict:
|
|
10
10
|
args = list(args or [])
|
|
11
|
-
if name
|
|
12
|
-
return {"ok": False, "error": "
|
|
11
|
+
if name in {"invoke", "devra"}:
|
|
12
|
+
return {"ok": False, "error": "%s cannot invoke itself" % name}
|
|
13
13
|
reg = catalog.registry(root)
|
|
14
14
|
item = reg.get(name)
|
|
15
15
|
if not item or item["kind"] != "spell" or item.get("run") is None:
|
|
@@ -98,7 +98,19 @@ def log_cast(
|
|
|
98
98
|
event_id=None,
|
|
99
99
|
root=None,
|
|
100
100
|
):
|
|
101
|
-
if spell in {
|
|
101
|
+
if spell in {
|
|
102
|
+
"grimoire",
|
|
103
|
+
"grimoire-seal",
|
|
104
|
+
"akashic",
|
|
105
|
+
"catalog",
|
|
106
|
+
"book",
|
|
107
|
+
"spellbook",
|
|
108
|
+
"devra",
|
|
109
|
+
"invoke",
|
|
110
|
+
"route",
|
|
111
|
+
"rites",
|
|
112
|
+
"procedures",
|
|
113
|
+
}:
|
|
102
114
|
return {"ok": True, "status": "excluded", "spell": spell}
|
|
103
115
|
try:
|
|
104
116
|
try:
|