techtree 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- techtree/__init__.py +35 -0
- techtree/__main__.py +14 -0
- techtree/canonical.py +239 -0
- techtree/catalog/__init__.py +25 -0
- techtree/catalog/repository.py +400 -0
- techtree/catalog/service.py +419 -0
- techtree/cli/__init__.py +1 -0
- techtree/cli/app.py +416 -0
- techtree/cli/commands/__init__.py +1 -0
- techtree/cli/commands/climb.py +1223 -0
- techtree/cli/commands/doctor.py +147 -0
- techtree/cli/commands/engine.py +207 -0
- techtree/cli/commands/proof.py +556 -0
- techtree/cli/commands/publish.py +447 -0
- techtree/cli/commands/release.py +303 -0
- techtree/cli/commands/run.py +1067 -0
- techtree/cli/commands/setup.py +181 -0
- techtree/cli/commands/skill.py +221 -0
- techtree/cli/commands/uplift.py +698 -0
- techtree/cli/commands/withdraw.py +212 -0
- techtree/cli/confirm.py +47 -0
- techtree/cli/context.py +96 -0
- techtree/cli/invoke.py +220 -0
- techtree/cli/output.py +280 -0
- techtree/constants.py +138 -0
- techtree/crypto.py +128 -0
- techtree/doctor/__init__.py +1 -0
- techtree/doctor/checks.py +675 -0
- techtree/doctor/execution_checks.py +435 -0
- techtree/doctor/service.py +326 -0
- techtree/drafts/__init__.py +32 -0
- techtree/drafts/source.py +146 -0
- techtree/drafts/store.py +992 -0
- techtree/engines/__init__.py +1 -0
- techtree/engines/bundle.py +251 -0
- techtree/engines/installer.py +679 -0
- techtree/engines/registry.py +235 -0
- techtree/engines/runner.py +170 -0
- techtree/errors.py +262 -0
- techtree/fs.py +234 -0
- techtree/harness.py +108 -0
- techtree/identity/__init__.py +41 -0
- techtree/identity/models.py +113 -0
- techtree/identity/service.py +199 -0
- techtree/identity/store.py +263 -0
- techtree/ids.py +85 -0
- techtree/manifests/__init__.py +39 -0
- techtree/manifests/builder.py +433 -0
- techtree/manifests/compare.py +376 -0
- techtree/models/__init__.py +282 -0
- techtree/models/base.py +201 -0
- techtree/models/campaign.py +484 -0
- techtree/models/catalog.py +227 -0
- techtree/models/cli.py +151 -0
- techtree/models/climb.py +254 -0
- techtree/models/data_policy.py +130 -0
- techtree/models/engine.py +156 -0
- techtree/models/episode_receipt.py +130 -0
- techtree/models/evaluation_backend.py +113 -0
- techtree/models/experiment.py +154 -0
- techtree/models/run.py +214 -0
- techtree/models/skill.py +156 -0
- techtree/models/uplift_report.py +158 -0
- techtree/models/validation.py +299 -0
- techtree/paths.py +116 -0
- techtree/presentation/__init__.py +31 -0
- techtree/presentation/build.py +1242 -0
- techtree/presentation/compact.py +246 -0
- techtree/presentation/evidence.py +169 -0
- techtree/presentation/models.py +358 -0
- techtree/presentation/rich.py +312 -0
- techtree/presentation/sanitize.py +156 -0
- techtree/publication/__init__.py +44 -0
- techtree/publication/address.py +180 -0
- techtree/publication/coordinates.py +26 -0
- techtree/publication/journal.py +212 -0
- techtree/publication/keccak.py +183 -0
- techtree/publication/models.py +209 -0
- techtree/publication/offer.py +35 -0
- techtree/publication/service.py +618 -0
- techtree/publication/transport.py +296 -0
- techtree/publication/verify.py +242 -0
- techtree/publication/withdraw.py +156 -0
- techtree/py.typed +0 -0
- techtree/receipts/__init__.py +52 -0
- techtree/receipts/bundle.py +578 -0
- techtree/receipts/compare.py +1065 -0
- techtree/receipts/episode.py +672 -0
- techtree/receipts/execution.py +630 -0
- techtree/receipts/observed.py +474 -0
- techtree/receipts/set.py +336 -0
- techtree/receipts/uplift.py +655 -0
- techtree/receipts/verify.py +1055 -0
- techtree/release/__init__.py +9 -0
- techtree/release/bootstrap.py +509 -0
- techtree/release/checks.py +376 -0
- techtree/release/document.py +125 -0
- techtree/release/generate.py +221 -0
- techtree/release/models.py +293 -0
- techtree/release/provenance.py +109 -0
- techtree/resources/catalog/campaigns/hello-world-climb.json +1 -0
- techtree/resources/catalog/catalog.json +32 -0
- techtree/resources/catalog/climbs/hello-world-climb.json +1 -0
- techtree/resources/catalog/data-policies/hello-world-climb.json +1 -0
- techtree/resources/catalog/taskset-validations/hello-world-climb.json +1 -0
- techtree/resources/catalog/validation-evidence/hello-world-climb.json +1 -0
- techtree/resources/engines/default/engine.json +20 -0
- techtree/resources/engines/default/packages/procedure-transfer-v1/procedure_transfer_v1/__init__.py +7 -0
- techtree/resources/engines/default/packages/procedure-transfer-v1/procedure_transfer_v1/algorithm.py +136 -0
- techtree/resources/engines/default/packages/procedure-transfer-v1/procedure_transfer_v1/dataset.py +156 -0
- techtree/resources/engines/default/packages/procedure-transfer-v1/procedure_transfer_v1/env.py +48 -0
- techtree/resources/engines/default/packages/procedure-transfer-v1/procedure_transfer_v1/taskset.py +163 -0
- techtree/resources/engines/default/packages/procedure-transfer-v1/pyproject.toml +13 -0
- techtree/resources/engines/default/pyproject.toml +23 -0
- techtree/resources/engines/default/tools/inspect_taskset.py +124 -0
- techtree/resources/engines/default/tools/normalize_eval_output.py +470 -0
- techtree/resources/engines/default/tools/normalize_validation.py +222 -0
- techtree/resources/engines/default/uv.lock +1758 -0
- techtree/resources/harness/hermes-agent-0.19.0.json +69 -0
- techtree/resources/release/build-provenance.json +4 -0
- techtree/resources/release/release-core.json +24 -0
- techtree/runs/__init__.py +31 -0
- techtree/runs/artifacts.py +750 -0
- techtree/runs/child_registry.py +228 -0
- techtree/runs/events.py +478 -0
- techtree/runs/executor.py +140 -0
- techtree/runs/fake.py +741 -0
- techtree/runs/launcher.py +253 -0
- techtree/runs/machine.py +489 -0
- techtree/runs/real.py +789 -0
- techtree/runs/service.py +616 -0
- techtree/runs/store.py +555 -0
- techtree/runs/validation.py +259 -0
- techtree/runs/variants.py +684 -0
- techtree/settings.py +143 -0
- techtree/skills/__init__.py +14 -0
- techtree/skills/archive.py +282 -0
- techtree/skills/policy.py +62 -0
- techtree/skills/scanner.py +394 -0
- techtree/skills/service.py +752 -0
- techtree/skills/starter.py +434 -0
- techtree/tasksets/__init__.py +1 -0
- techtree/tasksets/membership.py +269 -0
- techtree/tasksets/provider.py +207 -0
- techtree/tasksets/resolver.py +311 -0
- techtree/tasksets/service.py +484 -0
- techtree/tasksets/verifiers_cli.py +538 -0
- techtree/uplift/__init__.py +20 -0
- techtree/uplift/context.py +544 -0
- techtree/uplift/derive.py +203 -0
- techtree/uplift/public_tasks.py +151 -0
- techtree/uplift/service.py +719 -0
- techtree/uplift/source.py +160 -0
- techtree/verifiers/__init__.py +31 -0
- techtree/verifiers/budget.py +219 -0
- techtree/verifiers/child.py +633 -0
- techtree/verifiers/compiler.py +432 -0
- techtree/verifiers/config.py +365 -0
- techtree/verifiers/credentials.py +321 -0
- techtree/verifiers/image.py +126 -0
- techtree/verifiers/models.py +527 -0
- techtree/verifiers/outputs.py +368 -0
- techtree/verifiers/progress.py +192 -0
- techtree/verifiers/supervisor.py +341 -0
- techtree/verifiers/verify.py +782 -0
- techtree/version.py +39 -0
- techtree/worker/__init__.py +18 -0
- techtree/worker/execute.py +487 -0
- techtree/worker/main.py +57 -0
- techtree-0.1.0.dist-info/METADATA +344 -0
- techtree-0.1.0.dist-info/RECORD +174 -0
- techtree-0.1.0.dist-info/WHEEL +4 -0
- techtree-0.1.0.dist-info/entry_points.txt +3 -0
- techtree-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"candidate_skill":{"ownership":"participant","public_release":"required_for_climb","training_use":"prohibited"},"derived_artifacts":{"aggregate_scores":"public","anonymized_product_analytics":"allowed","redacted_trace_projection":"public","uplift_report":"public"},"id":"policy_7c67a4c051e4891ccf9d8ec27ea5e357","owner":{"account_ref":null,"kind":"participant"},"raw_episodes":{"local_retention":"allowed","public_release":"prohibited","reproduction_access":"consent_required","server_upload":"prohibited","training_use":"prohibited"},"revocation":{"future_use_revocable":true,"immutable_published_proofs_remain":true},"schema_version":"techtree.data-policy.v1alpha1","version":1}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"checks":[{"detail":"all 36 tasks passed this check","id":"upstream_gold","status":"passed"},{"detail":"all 36 tasks passed this check","id":"upstream_setup","status":"passed"},{"detail":"two independent inspections agreed on all 36 task hashes, in order","id":"membership_repeatability","status":"passed"},{"detail":"all 36 task hashes are distinct","id":"task_hash_uniqueness","status":"passed"},{"detail":"all 36 task hashes match in order","id":"committed_membership_match","status":"passed"},{"detail":"36 tasks, as the selection asks for","id":"expected_task_count","status":"passed"}],"engine_digest":"sha256:29b1bbb8327d8f1a9ade03ff4504695ad3783ae34aaaa559e5c6bf9fc95e879b","method":{"kind":"verifiers_validate","mode":"all","runtime":"subprocess","validator_revision":"b2e4e8157783b2c0dffc7821044c87f29f1c3ccf"},"normalized_evidence":{"digest":"sha256:991be5e42acbd48c6bd9aaf8e1f5a5a2478c0a0e4bf04ad4f2be84b702adee43","media_type":"application/json","relative_path":null,"size":6889},"schema_version":"techtree.taskset-validation.v1alpha1","status":"valid","taskset_lock_digest":"sha256:8bed6f7c7f8b1a703020db9fa0fe08b29e68df6abd0e8f06ffa229722c7d87e0","upstream_summary":{"error":0,"invalid":0,"missing":0,"mode":"all","recorded":36,"timeout":0,"total":36,"valid":36,"valid_rate":1}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"method":{"kind":"verifiers_validate","mode":"all","runtime":"subprocess","validator_revision":"b2e4e8157783b2c0dffc7821044c87f29f1c3ccf"},"schema_version":"techtree.validation-evidence.v1alpha1","summary":{"error":0,"invalid":0,"missing":0,"timeout":0,"total":36,"valid":36},"tasks":[{"gold":{"reason":"valid","valid":true},"position":0,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:af8a43bbaf38d332131d73ef9a5b995d9f330fdc37a777a12bef7c51c9fa0ed1"},{"gold":{"reason":"valid","valid":true},"position":1,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:e9a51458548dcfb10572fd9f032f00abdb298425114f68acdc074faa79229232"},{"gold":{"reason":"valid","valid":true},"position":2,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:bafa30550e9c0b09281b3b4b99cb467b9522babc9c2b9d97fee93abef26933b0"},{"gold":{"reason":"valid","valid":true},"position":3,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:1e74b2f5d62a6b25288d1d8ea3f85b6a0daf4a7697fe36d3f54b8534bb67b40d"},{"gold":{"reason":"valid","valid":true},"position":4,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:c05fd9db26808494349e9292ecde51a2c6b19e6d87e6f7d7080e2089829504f5"},{"gold":{"reason":"valid","valid":true},"position":5,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:02725a29cc06f2c883ad17e11a7fc2a09bd2b214df08f3c5c79e4941b54e315e"},{"gold":{"reason":"valid","valid":true},"position":6,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:206eb5646df5b41b67d28f0e42d370ceb3eb0d72a78cea97e5bbecb7e3841a9f"},{"gold":{"reason":"valid","valid":true},"position":7,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:c600be21a92a8c5401eaf645b8591b09f34052afe2ab61898d3be2edf8027cad"},{"gold":{"reason":"valid","valid":true},"position":8,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:b11c2add8339b16dbe85804f9b046e203a0b05db2b7fe9412a4dc45172c6555b"},{"gold":{"reason":"valid","valid":true},"position":9,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:bd835a69bbeb90d2b1c529aef6bac0c47a8b83750967bf4b64373a90540a07a4"},{"gold":{"reason":"valid","valid":true},"position":10,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:0a5bde37b05e74be39c62f4418d4812a123d627bc627591fb02dde124b246426"},{"gold":{"reason":"valid","valid":true},"position":11,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:f15ce47698160cd33fe7a0eb5e40a4cc7977624dd2bdf481ffee69b6204f26b3"},{"gold":{"reason":"valid","valid":true},"position":12,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:4fb4ddcab900a74eb7cb6ff6a730cc07b5a244535f40f6ddb6aa726cb2796596"},{"gold":{"reason":"valid","valid":true},"position":13,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:84d83849562386b699e048a91c5671e0f55b49098c9dfac9711a0895766caef3"},{"gold":{"reason":"valid","valid":true},"position":14,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:e08bb7c7a18a57a83d2ad8dba412c416a8746f708f54b8a29efc0355cabbdb45"},{"gold":{"reason":"valid","valid":true},"position":15,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:775f95710c5b09fd79e5720554b764f8a1c938063e5743977efe9a4f9d6dc12b"},{"gold":{"reason":"valid","valid":true},"position":16,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:832e70ff2ab29bfc83da704344417f0c9be2af2935247178ecd1cedc00477097"},{"gold":{"reason":"valid","valid":true},"position":17,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:5ef9194a49f5ada8a059b52cee70090a53df2bd5b415bf9ed8533287f3020dfc"},{"gold":{"reason":"valid","valid":true},"position":18,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:b195109ade431bf058e12c4ae1dff6c7bf05d4770be9af9ed27d8f588e95c910"},{"gold":{"reason":"valid","valid":true},"position":19,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:67eae183c9a688ab5172104c8f8e6380a3c052d367e5bd05964618f5f575bcd8"},{"gold":{"reason":"valid","valid":true},"position":20,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:cb5651849ccdc4309b9931918392831a2afc7d1b82e6a976a8777a23e73057aa"},{"gold":{"reason":"valid","valid":true},"position":21,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:391c080f51aa41130367d01e43ff21f80ef915274dd19b2f1a4aaf76380f8f13"},{"gold":{"reason":"valid","valid":true},"position":22,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:6c39dc6c8c62d0b471e3e40cc560d6cf105632c62e40de8ab21f00e1f3dcd8dc"},{"gold":{"reason":"valid","valid":true},"position":23,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:f5d73f388d604fc4df9afe63c70ca81f22646faad2bae99e24b1be0b5b6e239a"},{"gold":{"reason":"valid","valid":true},"position":24,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:c6bb62c1b970b25d39823748dd9cb087884cfb7360668f8c405d870af26e223e"},{"gold":{"reason":"valid","valid":true},"position":25,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:23c6f7a31ede5aa224788e4408ae1462ca57c559175232d740de6a139b02a5b4"},{"gold":{"reason":"valid","valid":true},"position":26,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:13fe52ddfdeab29466e3ed21db540a08d169e09d338e86852f96387f2272795d"},{"gold":{"reason":"valid","valid":true},"position":27,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:702eb0abb56d4554d7e9b8d75f15cf3d7ecfc0c8c9f83cf1c6c3caa25c5865f5"},{"gold":{"reason":"valid","valid":true},"position":28,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:aee7f9a4999dce081dbd0ce6ab65db37ffe9bb88d9b4a07b944f376fef0a14ad"},{"gold":{"reason":"valid","valid":true},"position":29,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:4b6a3d718933e312c05adff201cd14ab1d58b0eb5c0a0d32faccedc09cb9af68"},{"gold":{"reason":"valid","valid":true},"position":30,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:8b5ae57c98f3963e91dd611d4cfc37da07c80d4b3c0091ed7b4a76175376381a"},{"gold":{"reason":"valid","valid":true},"position":31,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:98f86f8d3663dcf3d0f32b6b1f9ef44913bb144355ecbcd89b8e4c96337b6964"},{"gold":{"reason":"valid","valid":true},"position":32,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:3efcd8d42d8adfce2038f5e5d8c88c3ec1d30d6ae3379c4727ea711b28e1929d"},{"gold":{"reason":"valid","valid":true},"position":33,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:bd2815069c78bced9ef23d36770c941b27753dad15db3e6c3a90c197181202a1"},{"gold":{"reason":"valid","valid":true},"position":34,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:08c8263a76b1d93beb586c8c39f0469721455cd08d517b15bcf827cf09ac0755"},{"gold":{"reason":"valid","valid":true},"position":35,"setup":{"reason":"valid","valid":true},"task_hash":"sha256:0777a89a3da39284a1765937c3ce1cea7af2ac27a98ffee32e86a2a1fccca9b5"}],"taskset_lock_digest":"sha256:8bed6f7c7f8b1a703020db9fa0fe08b29e68df6abd0e8f06ffa229722c7d87e0"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "default",
|
|
3
|
+
"packages": [
|
|
4
|
+
{
|
|
5
|
+
"name": "procedure-transfer-v1",
|
|
6
|
+
"source_digest": "sha256:f42a0d5e968478af40c703645d247ef043f115f6801d3b497eca5fab47261a7c",
|
|
7
|
+
"version": "0.1.0"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"python_version": "3.12",
|
|
11
|
+
"schema_version": "techtree.engine.v1alpha1",
|
|
12
|
+
"supported_hosts": [
|
|
13
|
+
"darwin/amd64",
|
|
14
|
+
"darwin/arm64",
|
|
15
|
+
"linux/amd64",
|
|
16
|
+
"linux/arm64"
|
|
17
|
+
],
|
|
18
|
+
"verifiers_revision": "b2e4e8157783b2c0dffc7821044c87f29f1c3ccf",
|
|
19
|
+
"verifiers_version": "0.3.1"
|
|
20
|
+
}
|
techtree/resources/engines/default/packages/procedure-transfer-v1/procedure_transfer_v1/algorithm.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""BranchCode v1: the deterministic procedure the reference taskset scores.
|
|
2
|
+
|
|
3
|
+
The procedure is specified in section 22.2 of the Climb v0.1 WP0-WP5
|
|
4
|
+
specification:
|
|
5
|
+
|
|
6
|
+
1. Normalize the input to lowercase ASCII.
|
|
7
|
+
2. Reject empty or unsupported text.
|
|
8
|
+
3. Map ``a=1`` through ``z=26``.
|
|
9
|
+
4. Multiply each letter value by its one-indexed position.
|
|
10
|
+
5. Sum the products.
|
|
11
|
+
6. Count the distinct characters.
|
|
12
|
+
7. Add seven times the distinct count.
|
|
13
|
+
8. Reduce modulo 97.
|
|
14
|
+
9. Format as ``BRANCH-XX``.
|
|
15
|
+
|
|
16
|
+
Every function here is pure and deterministic: no environment access, no
|
|
17
|
+
randomness, no clocks, no network, no I/O.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"ALPHABET",
|
|
24
|
+
"DISTINCT_WEIGHT",
|
|
25
|
+
"MODULUS",
|
|
26
|
+
"branch_code",
|
|
27
|
+
"branch_code_number",
|
|
28
|
+
"normalize_input",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
ALPHABET = "abcdefghijklmnopqrstuvwxyz"
|
|
32
|
+
"""The only characters BranchCode v1 accepts after normalization."""
|
|
33
|
+
|
|
34
|
+
DISTINCT_WEIGHT = 7
|
|
35
|
+
"""Multiplier applied to the distinct-character count (step 7)."""
|
|
36
|
+
|
|
37
|
+
MODULUS = 97
|
|
38
|
+
"""Modulus applied to the weighted sum (step 8)."""
|
|
39
|
+
|
|
40
|
+
_LETTER_VALUES = {letter: index for index, letter in enumerate(ALPHABET, start=1)}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def normalize_input(value: str) -> str:
|
|
44
|
+
"""Strip, lowercase, and require ASCII ``a``-``z``.
|
|
45
|
+
|
|
46
|
+
Surrounding whitespace is removed and the remaining text is lowercased.
|
|
47
|
+
The result must be non-empty and contain only the twenty-six ASCII
|
|
48
|
+
lowercase letters; anything else is unsupported input.
|
|
49
|
+
|
|
50
|
+
>>> normalize_input(" Maple ")
|
|
51
|
+
'maple'
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
value: Raw candidate input.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
The normalized lowercase ASCII form of ``value``.
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
TypeError: If ``value`` is not a string.
|
|
61
|
+
ValueError: If the normalized text is empty or holds any character
|
|
62
|
+
outside ``a``-``z``.
|
|
63
|
+
"""
|
|
64
|
+
if not isinstance(value, str):
|
|
65
|
+
raise TypeError(
|
|
66
|
+
f"BranchCode input must be a string, got {type(value).__name__}"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
normalized = value.strip().lower()
|
|
70
|
+
if not normalized:
|
|
71
|
+
raise ValueError(
|
|
72
|
+
"BranchCode input must not be empty after stripping whitespace"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
unsupported = sorted(
|
|
76
|
+
{character for character in normalized if character not in _LETTER_VALUES}
|
|
77
|
+
)
|
|
78
|
+
if unsupported:
|
|
79
|
+
rendered = ", ".join(repr(character) for character in unsupported)
|
|
80
|
+
raise ValueError(
|
|
81
|
+
f"BranchCode input must be ASCII a-z only; "
|
|
82
|
+
f"unsupported characters: {rendered}"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return normalized
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def branch_code_number(value: str) -> int:
|
|
89
|
+
"""Return the BranchCode v1 number in ``0..96``.
|
|
90
|
+
|
|
91
|
+
>>> branch_code_number("maple")
|
|
92
|
+
74
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
value: Raw candidate input; normalized before scoring.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
The weighted positional sum plus seven times the distinct-character
|
|
99
|
+
count, reduced modulo 97.
|
|
100
|
+
|
|
101
|
+
Raises:
|
|
102
|
+
TypeError: If ``value`` is not a string.
|
|
103
|
+
ValueError: If ``value`` is empty or not ASCII ``a``-``z``.
|
|
104
|
+
"""
|
|
105
|
+
normalized = normalize_input(value)
|
|
106
|
+
|
|
107
|
+
weighted_sum = sum(
|
|
108
|
+
_LETTER_VALUES[character] * position
|
|
109
|
+
for position, character in enumerate(normalized, start=1)
|
|
110
|
+
)
|
|
111
|
+
distinct_count = len(set(normalized))
|
|
112
|
+
|
|
113
|
+
return (weighted_sum + DISTINCT_WEIGHT * distinct_count) % MODULUS
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def branch_code(value: str) -> str:
|
|
117
|
+
"""Return the ``BRANCH-XX`` token for ``value``.
|
|
118
|
+
|
|
119
|
+
The numeric part is always two digits, zero-padded.
|
|
120
|
+
|
|
121
|
+
>>> branch_code("birch")
|
|
122
|
+
'BRANCH-64'
|
|
123
|
+
>>> branch_code("acorn")
|
|
124
|
+
'BRANCH-35'
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
value: Raw candidate input; normalized before scoring.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
The formatted ``BRANCH-XX`` token.
|
|
131
|
+
|
|
132
|
+
Raises:
|
|
133
|
+
TypeError: If ``value`` is not a string.
|
|
134
|
+
ValueError: If ``value`` is empty or not ASCII ``a``-``z``.
|
|
135
|
+
"""
|
|
136
|
+
return f"BRANCH-{branch_code_number(value):02d}"
|
techtree/resources/engines/default/packages/procedure-transfer-v1/procedure_transfer_v1/dataset.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""The frozen proving dataset for the BranchCode v1 reference taskset.
|
|
2
|
+
|
|
3
|
+
``PROVING_INPUTS`` is a literal, hand-written tuple. It is never generated,
|
|
4
|
+
sampled, shuffled, or extended at runtime: the ordered membership of this
|
|
5
|
+
tuple is what the Campaign membership commitment pins, so any change to the
|
|
6
|
+
contents *or* the order is a breaking change to every existing commitment.
|
|
7
|
+
|
|
8
|
+
Ordering rule (stable and auditable): by length ascending, then
|
|
9
|
+
alphabetically within each length.
|
|
10
|
+
|
|
11
|
+
Composition rule, and the reason the tuple looks the way it does: exactly
|
|
12
|
+
twenty-four of the thirty-six inputs use each character only once, and the
|
|
13
|
+
other twelve repeat at least one. That split is load-bearing. Step 7 adds
|
|
14
|
+
seven times the *distinct*-character count, so an input whose characters are
|
|
15
|
+
all different is the one case where counting characters the naive way — every
|
|
16
|
+
character, repeats included — still lands on the right answer. The
|
|
17
|
+
introductory Climb's starter Skill counts the naive way on purpose, and the
|
|
18
|
+
twenty-four-to-twelve split is what puts its score in the calibrated band with
|
|
19
|
+
headroom left to improve. Decisions document 0012 fixes the split; changing
|
|
20
|
+
which inputs are here moves it, so the count is checked by the repository's
|
|
21
|
+
own tests rather than left to whoever edits next.
|
|
22
|
+
|
|
23
|
+
None of these strings ever appears in a documentation example, a docstring,
|
|
24
|
+
or a candidate skill; the worked examples are reserved separately in
|
|
25
|
+
``DOCUMENTATION_EXAMPLES`` so the proving inputs stay unseen.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
from procedure_transfer_v1.algorithm import normalize_input
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"DOCUMENTATION_EXAMPLES",
|
|
34
|
+
"MAX_INPUT_LENGTH",
|
|
35
|
+
"MIN_INPUT_LENGTH",
|
|
36
|
+
"MIN_PROVING_INPUTS",
|
|
37
|
+
"PROVING_INPUTS",
|
|
38
|
+
"proving_inputs",
|
|
39
|
+
"validate_dataset",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
MIN_PROVING_INPUTS = 32
|
|
43
|
+
"""Specification floor on the size of the frozen dataset."""
|
|
44
|
+
|
|
45
|
+
MIN_INPUT_LENGTH = 4
|
|
46
|
+
"""Shortest permitted proving input."""
|
|
47
|
+
|
|
48
|
+
MAX_INPUT_LENGTH = 12
|
|
49
|
+
"""Longest permitted proving input."""
|
|
50
|
+
|
|
51
|
+
DOCUMENTATION_EXAMPLES = frozenset({"acorn", "birch", "maple"})
|
|
52
|
+
"""Worked-example inputs reserved for documentation and never proven against."""
|
|
53
|
+
|
|
54
|
+
PROVING_INPUTS: tuple[str, ...] = (
|
|
55
|
+
# length 5
|
|
56
|
+
"alder",
|
|
57
|
+
"aspen",
|
|
58
|
+
"carob",
|
|
59
|
+
"cedar",
|
|
60
|
+
"hazel",
|
|
61
|
+
"larch",
|
|
62
|
+
"rowan",
|
|
63
|
+
# length 6
|
|
64
|
+
"almond",
|
|
65
|
+
"cashew",
|
|
66
|
+
"spruce",
|
|
67
|
+
"willow",
|
|
68
|
+
# length 7
|
|
69
|
+
"apricot",
|
|
70
|
+
"dogwood",
|
|
71
|
+
"hemlock",
|
|
72
|
+
"juniper",
|
|
73
|
+
"sequoia",
|
|
74
|
+
# length 8
|
|
75
|
+
"blackgum",
|
|
76
|
+
"hazelnut",
|
|
77
|
+
"hornbeam",
|
|
78
|
+
"ironwood",
|
|
79
|
+
"mangrove",
|
|
80
|
+
"mulberry",
|
|
81
|
+
"sycamore",
|
|
82
|
+
"tamarack",
|
|
83
|
+
# length 9
|
|
84
|
+
"buckthorn",
|
|
85
|
+
"jacaranda",
|
|
86
|
+
"jackfruit",
|
|
87
|
+
"mockernut",
|
|
88
|
+
"sassafras",
|
|
89
|
+
"waxmyrtle",
|
|
90
|
+
# length 10
|
|
91
|
+
"blackthorn",
|
|
92
|
+
"cottonwood",
|
|
93
|
+
"elderberry",
|
|
94
|
+
"eucalyptus",
|
|
95
|
+
"sandalwood",
|
|
96
|
+
# length 11
|
|
97
|
+
"bristlecone",
|
|
98
|
+
)
|
|
99
|
+
"""The frozen, ordered proving inputs. Do not reorder, add, or remove."""
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def proving_inputs() -> tuple[str, ...]:
|
|
103
|
+
"""Return the immutable, ordered proving inputs.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
``PROVING_INPUTS`` itself; tuples are immutable, so callers cannot
|
|
107
|
+
disturb the committed order.
|
|
108
|
+
"""
|
|
109
|
+
return PROVING_INPUTS
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def validate_dataset() -> None:
|
|
113
|
+
"""Check every invariant the frozen dataset must satisfy.
|
|
114
|
+
|
|
115
|
+
Verifies the dataset size floor, uniqueness, the ASCII ``a``-``z``
|
|
116
|
+
charset, the length bounds, the length-then-alphabetical order, and that
|
|
117
|
+
no proving input collides with a reserved documentation example.
|
|
118
|
+
|
|
119
|
+
Raises:
|
|
120
|
+
ValueError: On the first invariant that fails.
|
|
121
|
+
"""
|
|
122
|
+
count = len(PROVING_INPUTS)
|
|
123
|
+
if count < MIN_PROVING_INPUTS:
|
|
124
|
+
raise ValueError(
|
|
125
|
+
f"PROVING_INPUTS must hold at least {MIN_PROVING_INPUTS} entries, "
|
|
126
|
+
f"found {count}"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
seen: set[str] = set()
|
|
130
|
+
for entry in PROVING_INPUTS:
|
|
131
|
+
if entry in seen:
|
|
132
|
+
raise ValueError(f"PROVING_INPUTS contains a duplicate entry: {entry!r}")
|
|
133
|
+
seen.add(entry)
|
|
134
|
+
|
|
135
|
+
if normalize_input(entry) != entry:
|
|
136
|
+
raise ValueError(
|
|
137
|
+
"PROVING_INPUTS entry must already be normalized lowercase a-z: "
|
|
138
|
+
f"{entry!r}"
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if not MIN_INPUT_LENGTH <= len(entry) <= MAX_INPUT_LENGTH:
|
|
142
|
+
raise ValueError(
|
|
143
|
+
f"PROVING_INPUTS entry must be {MIN_INPUT_LENGTH}-{MAX_INPUT_LENGTH} "
|
|
144
|
+
f"characters, found {len(entry)}: {entry!r}"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
if entry in DOCUMENTATION_EXAMPLES:
|
|
148
|
+
raise ValueError(
|
|
149
|
+
f"PROVING_INPUTS entry overlaps a documentation example: {entry!r}"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
ordered = tuple(sorted(PROVING_INPUTS, key=lambda entry: (len(entry), entry)))
|
|
153
|
+
if ordered != PROVING_INPUTS:
|
|
154
|
+
raise ValueError(
|
|
155
|
+
"PROVING_INPUTS must be ordered by length ascending, then alphabetically"
|
|
156
|
+
)
|
techtree/resources/engines/default/packages/procedure-transfer-v1/procedure_transfer_v1/env.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""The environment that gives the evaluated role its real name. Spec 6.5.
|
|
2
|
+
|
|
3
|
+
Verifiers' default ``SingleAgentEnv`` seats its one agent in a field called
|
|
4
|
+
``agent``, and the field name is what every trace records as ``agent.name``.
|
|
5
|
+
Techtree's scientific model calls the evaluated role ``subject``, and receipts
|
|
6
|
+
group traces by declared role, so the choice is between renaming a recorded
|
|
7
|
+
role afterwards for presentation and making the role real where it is
|
|
8
|
+
recorded. Renaming after the fact would mean a receipt describing something the
|
|
9
|
+
raw evidence never said. This environment makes it real instead: the seat is a
|
|
10
|
+
field named ``subject``, so every trace this package produces records
|
|
11
|
+
``agent.name == "subject"`` and no trace anywhere records ``agent``.
|
|
12
|
+
|
|
13
|
+
That the package can export a Taskset and an Env together is not a trick.
|
|
14
|
+
Verifiers resolves plugins by requested base type, so the taskset loader sees
|
|
15
|
+
exactly one Taskset and the environment loader sees exactly one Env. The
|
|
16
|
+
behaviour was proven against the pinned commit before this file was written;
|
|
17
|
+
``docs/verifiers-eval.md`` records it.
|
|
18
|
+
|
|
19
|
+
The environment does one thing and holds no policy. Everything about how the
|
|
20
|
+
subject is configured — model, harness, runtime, skills — arrives through the
|
|
21
|
+
compiled configuration, because a knob here would be a second place an
|
|
22
|
+
experiment could differ.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import verifiers.v1 as vf
|
|
28
|
+
|
|
29
|
+
__all__ = ["ProcedureTransferEnv", "ProcedureTransferEnvConfig"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ProcedureTransferEnvConfig(vf.EnvConfig):
|
|
33
|
+
"""The one seat, named for the role it plays."""
|
|
34
|
+
|
|
35
|
+
subject: vf.AgentConfig = vf.AgentConfig()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ProcedureTransferEnv(vf.Env[ProcedureTransferEnvConfig]):
|
|
39
|
+
"""One episode is the subject attempting one task."""
|
|
40
|
+
|
|
41
|
+
async def run(self, task: vf.Task, agents: vf.Agents) -> None:
|
|
42
|
+
"""Play one task through the subject seat.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
task: The task this episode is seeded from.
|
|
46
|
+
agents: The episode's agents, addressed by seat name.
|
|
47
|
+
"""
|
|
48
|
+
await agents.subject.run(task)
|
techtree/resources/engines/default/packages/procedure-transfer-v1/procedure_transfer_v1/taskset.py
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""The Verifiers Taskset that scores BranchCode v1 procedure transfer.
|
|
2
|
+
|
|
3
|
+
Spec section 22.5. Shapes here were proven against the pinned Verifiers commit
|
|
4
|
+
`b2e4e8157783b2c0dffc7821044c87f29f1c3ccf` by the PI0 preflight; see
|
|
5
|
+
`docs/verifiers-pin-0.3.1.md`.
|
|
6
|
+
|
|
7
|
+
The prompt deliberately carries the *name* of the procedure and the *shape* of
|
|
8
|
+
the expected answer, and nothing else. BranchCode v1 itself — letter values,
|
|
9
|
+
positional weighting, the distinct-character term, the modulus — never appears
|
|
10
|
+
here. A subject that has not been given the procedure cannot recover it from
|
|
11
|
+
the prompt; that gap is exactly what the reference taskset measures.
|
|
12
|
+
|
|
13
|
+
This module is the only part of the package that imports Verifiers. It runs
|
|
14
|
+
inside the managed engine environment, never inside the ordinary Techtree
|
|
15
|
+
environment.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from collections.abc import Iterable
|
|
21
|
+
|
|
22
|
+
import verifiers.v1 as vf
|
|
23
|
+
|
|
24
|
+
from procedure_transfer_v1.algorithm import (
|
|
25
|
+
MODULUS,
|
|
26
|
+
branch_code,
|
|
27
|
+
branch_code_number,
|
|
28
|
+
)
|
|
29
|
+
from procedure_transfer_v1.dataset import proving_inputs, validate_dataset
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"PROMPT_TEMPLATE",
|
|
33
|
+
"TASK_NAME_TEMPLATE",
|
|
34
|
+
"ProcedureTransferData",
|
|
35
|
+
"ProcedureTransferTask",
|
|
36
|
+
"ProcedureTransferTaskset",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
PROMPT_TEMPLATE = (
|
|
40
|
+
"Apply BranchCode v1 to this input:\n"
|
|
41
|
+
"\n"
|
|
42
|
+
"{input_text}\n"
|
|
43
|
+
"\n"
|
|
44
|
+
"Return only the final BRANCH-XX token."
|
|
45
|
+
)
|
|
46
|
+
"""Spec section 22.5, verbatim. Never add procedure detail to this string."""
|
|
47
|
+
|
|
48
|
+
TASK_NAME_TEMPLATE = "branch-code-{index:03d}"
|
|
49
|
+
"""Stable task names, one per proving input, in dataset order."""
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def normalize_reply(reply: str) -> str:
|
|
53
|
+
"""Return the comparable form of a subject reply.
|
|
54
|
+
|
|
55
|
+
A reply is trimmed and upper-cased before it is compared with the hidden
|
|
56
|
+
answer. Nothing is extracted from surrounding prose: the prompt asks for
|
|
57
|
+
the token alone, so a reply that buries the token in a sentence is wrong.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
reply: Raw subject reply text.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
The trimmed, upper-cased reply.
|
|
64
|
+
"""
|
|
65
|
+
return reply.strip().upper()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class ProcedureTransferData(vf.TaskData):
|
|
69
|
+
"""Wire data for one BranchCode task.
|
|
70
|
+
|
|
71
|
+
``answer`` is the oracle result. It is part of the task's content hash and
|
|
72
|
+
is never placed in the prompt.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
input_text: str
|
|
76
|
+
answer: str
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class ProcedureTransferTask(vf.Task[ProcedureTransferData]):
|
|
80
|
+
"""One proving input, scored by exact match against the hidden answer."""
|
|
81
|
+
|
|
82
|
+
def score_reply(self, reply: str) -> float:
|
|
83
|
+
"""Return 1.0 for an exact match with the hidden answer, else 0.0.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
reply: Raw subject reply text.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
``1.0`` or ``0.0``.
|
|
90
|
+
"""
|
|
91
|
+
return 1.0 if normalize_reply(reply) == self.data.answer else 0.0
|
|
92
|
+
|
|
93
|
+
@vf.reward
|
|
94
|
+
async def exact_match(self, trace: vf.Trace) -> float:
|
|
95
|
+
"""Score the last assistant reply in ``trace``.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
trace: The rollout trace under evaluation.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
``1.0`` or ``0.0``.
|
|
102
|
+
"""
|
|
103
|
+
return self.score_reply(trace.last_reply)
|
|
104
|
+
|
|
105
|
+
async def validate(self, runtime: vf.Runtime) -> bool:
|
|
106
|
+
"""Prove this task is well formed without consulting a model.
|
|
107
|
+
|
|
108
|
+
Four independent conditions, all required:
|
|
109
|
+
|
|
110
|
+
1. The oracle recomputed from ``input_text`` equals the stored answer.
|
|
111
|
+
2. A stored answer exists at all.
|
|
112
|
+
3. The correct answer scores 1.0.
|
|
113
|
+
4. A well-formed but wrong token scores 0.0.
|
|
114
|
+
|
|
115
|
+
Condition 4 uses the next code in the modular sequence rather than a
|
|
116
|
+
malformed placeholder, so the negative control is a genuine near miss
|
|
117
|
+
that only exact matching rejects.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
runtime: The Verifiers runtime; unused, this check is model-free.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
True when every condition holds.
|
|
124
|
+
"""
|
|
125
|
+
del runtime
|
|
126
|
+
|
|
127
|
+
oracle = branch_code(self.data.input_text)
|
|
128
|
+
near_miss_number = (branch_code_number(self.data.input_text) + 1) % MODULUS
|
|
129
|
+
near_miss = f"BRANCH-{near_miss_number:02d}"
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
bool(self.data.answer)
|
|
133
|
+
and oracle == self.data.answer
|
|
134
|
+
and self.score_reply(self.data.answer) == 1.0
|
|
135
|
+
and self.score_reply(near_miss) == 0.0
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class ProcedureTransferTaskset(vf.Taskset[ProcedureTransferTask, vf.TasksetConfig]):
|
|
140
|
+
"""The frozen proving inputs, one deterministic task each, in dataset order."""
|
|
141
|
+
|
|
142
|
+
def load(self) -> Iterable[ProcedureTransferTask]:
|
|
143
|
+
"""Yield one task per proving input.
|
|
144
|
+
|
|
145
|
+
Yield order is the frozen dataset order, which is what the Campaign
|
|
146
|
+
membership commitment pins.
|
|
147
|
+
|
|
148
|
+
Yields:
|
|
149
|
+
One :class:`ProcedureTransferTask` per proving input.
|
|
150
|
+
"""
|
|
151
|
+
validate_dataset()
|
|
152
|
+
|
|
153
|
+
for index, input_text in enumerate(proving_inputs()):
|
|
154
|
+
yield ProcedureTransferTask(
|
|
155
|
+
ProcedureTransferData(
|
|
156
|
+
idx=index,
|
|
157
|
+
name=TASK_NAME_TEMPLATE.format(index=index),
|
|
158
|
+
prompt=PROMPT_TEMPLATE.format(input_text=input_text),
|
|
159
|
+
input_text=input_text,
|
|
160
|
+
answer=branch_code(input_text),
|
|
161
|
+
),
|
|
162
|
+
self.config.task,
|
|
163
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "procedure-transfer-v1"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Deterministic BranchCode procedure-transfer taskset"
|
|
5
|
+
requires-python = ">=3.12"
|
|
6
|
+
dependencies = []
|
|
7
|
+
|
|
8
|
+
[build-system]
|
|
9
|
+
requires = ["hatchling"]
|
|
10
|
+
build-backend = "hatchling.build"
|
|
11
|
+
|
|
12
|
+
[tool.hatch.build.targets.wheel]
|
|
13
|
+
packages = ["procedure_transfer_v1"]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# The managed Techtree evaluation engine.
|
|
2
|
+
#
|
|
3
|
+
# Generated by tools/build_engine_bundle.py. Do not edit by hand: the file is
|
|
4
|
+
# part of the engine bundle digest, and `make generated-check` rewrites it in a
|
|
5
|
+
# throwaway tree and fails on any difference.
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "techtree-engine-default"
|
|
9
|
+
version = "0.1.0"
|
|
10
|
+
description = "Pinned Verifiers environment and reference tasksets for Techtree."
|
|
11
|
+
requires-python = ">=3.12,<3.13"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"procedure-transfer-v1",
|
|
14
|
+
"verifiers",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[tool.uv]
|
|
18
|
+
# The engine project is an environment, not a distribution. Nothing installs it.
|
|
19
|
+
package = false
|
|
20
|
+
|
|
21
|
+
[tool.uv.sources]
|
|
22
|
+
procedure-transfer-v1 = { path = "packages/procedure-transfer-v1", editable = true }
|
|
23
|
+
verifiers = { git = "https://github.com/PrimeIntellect-ai/verifiers", rev = "b2e4e8157783b2c0dffc7821044c87f29f1c3ccf" }
|