hyperloop 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.
- hyperloop/__init__.py +0 -0
- hyperloop/__main__.py +5 -0
- hyperloop/adapters/__init__.py +0 -0
- hyperloop/adapters/git_state.py +254 -0
- hyperloop/adapters/local.py +273 -0
- hyperloop/cli.py +166 -0
- hyperloop/compose.py +126 -0
- hyperloop/config.py +161 -0
- hyperloop/domain/__init__.py +0 -0
- hyperloop/domain/decide.py +104 -0
- hyperloop/domain/deps.py +66 -0
- hyperloop/domain/model.py +221 -0
- hyperloop/domain/pipeline.py +306 -0
- hyperloop/loop.py +510 -0
- hyperloop/ports/__init__.py +0 -0
- hyperloop/ports/pr.py +32 -0
- hyperloop/ports/runtime.py +37 -0
- hyperloop/ports/state.py +61 -0
- hyperloop/pr.py +212 -0
- hyperloop-0.1.0.dist-info/METADATA +253 -0
- hyperloop-0.1.0.dist-info/RECORD +23 -0
- hyperloop-0.1.0.dist-info/WHEEL +4 -0
- hyperloop-0.1.0.dist-info/entry_points.txt +2 -0
hyperloop/pr.py
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"""PR manager — draft PR lifecycle: creation, labeling, gate polling, merge.
|
|
2
|
+
|
|
3
|
+
Uses the `gh` CLI for all GitHub operations. The interface is matched by
|
|
4
|
+
FakePRManager (tests/fakes/pr.py) for testing without a real GitHub repo.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
import re
|
|
12
|
+
import subprocess
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class PRManager:
|
|
18
|
+
"""Manages draft PR lifecycle: creation, labeling, gate polling, merge."""
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
repo: str,
|
|
23
|
+
merge_strategy: str = "squash",
|
|
24
|
+
delete_branch: bool = True,
|
|
25
|
+
) -> None:
|
|
26
|
+
self.repo = repo
|
|
27
|
+
self.merge_strategy = merge_strategy
|
|
28
|
+
self.delete_branch = delete_branch
|
|
29
|
+
|
|
30
|
+
def create_draft(self, task_id: str, branch: str, title: str, spec_ref: str) -> str:
|
|
31
|
+
"""Create a draft PR. Returns PR URL. Adds spec/task labels."""
|
|
32
|
+
result = subprocess.run(
|
|
33
|
+
[
|
|
34
|
+
"gh",
|
|
35
|
+
"pr",
|
|
36
|
+
"create",
|
|
37
|
+
"--draft",
|
|
38
|
+
"--head",
|
|
39
|
+
branch,
|
|
40
|
+
"--title",
|
|
41
|
+
title,
|
|
42
|
+
"--body",
|
|
43
|
+
"",
|
|
44
|
+
"--repo",
|
|
45
|
+
self.repo,
|
|
46
|
+
],
|
|
47
|
+
capture_output=True,
|
|
48
|
+
text=True,
|
|
49
|
+
check=True,
|
|
50
|
+
)
|
|
51
|
+
pr_url = result.stdout.strip()
|
|
52
|
+
|
|
53
|
+
spec_name = _spec_name_from_ref(spec_ref)
|
|
54
|
+
subprocess.run(
|
|
55
|
+
[
|
|
56
|
+
"gh",
|
|
57
|
+
"pr",
|
|
58
|
+
"edit",
|
|
59
|
+
pr_url,
|
|
60
|
+
"--add-label",
|
|
61
|
+
f"task/{task_id}",
|
|
62
|
+
"--add-label",
|
|
63
|
+
f"spec/{spec_name}",
|
|
64
|
+
"--repo",
|
|
65
|
+
self.repo,
|
|
66
|
+
],
|
|
67
|
+
capture_output=True,
|
|
68
|
+
text=True,
|
|
69
|
+
check=True,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
logger.info("Created draft PR %s for task %s", pr_url, task_id)
|
|
73
|
+
return pr_url
|
|
74
|
+
|
|
75
|
+
def check_gate(self, pr_url: str, gate: str) -> bool:
|
|
76
|
+
"""Check if a gate signal is present. v1: checks for 'lgtm' label.
|
|
77
|
+
|
|
78
|
+
Returns True if gate is cleared. Removes the label to prevent re-triggering.
|
|
79
|
+
"""
|
|
80
|
+
result = subprocess.run(
|
|
81
|
+
[
|
|
82
|
+
"gh",
|
|
83
|
+
"pr",
|
|
84
|
+
"view",
|
|
85
|
+
pr_url,
|
|
86
|
+
"--json",
|
|
87
|
+
"labels",
|
|
88
|
+
"--repo",
|
|
89
|
+
self.repo,
|
|
90
|
+
],
|
|
91
|
+
capture_output=True,
|
|
92
|
+
text=True,
|
|
93
|
+
check=True,
|
|
94
|
+
)
|
|
95
|
+
data = json.loads(result.stdout)
|
|
96
|
+
label_names = {label["name"] for label in data.get("labels", [])}
|
|
97
|
+
|
|
98
|
+
if "lgtm" in label_names:
|
|
99
|
+
subprocess.run(
|
|
100
|
+
[
|
|
101
|
+
"gh",
|
|
102
|
+
"pr",
|
|
103
|
+
"edit",
|
|
104
|
+
pr_url,
|
|
105
|
+
"--remove-label",
|
|
106
|
+
"lgtm",
|
|
107
|
+
"--repo",
|
|
108
|
+
self.repo,
|
|
109
|
+
],
|
|
110
|
+
capture_output=True,
|
|
111
|
+
text=True,
|
|
112
|
+
check=True,
|
|
113
|
+
)
|
|
114
|
+
logger.info("Gate '%s' cleared for PR %s (lgtm label found and removed)", gate, pr_url)
|
|
115
|
+
return True
|
|
116
|
+
|
|
117
|
+
return False
|
|
118
|
+
|
|
119
|
+
def mark_ready(self, pr_url: str) -> None:
|
|
120
|
+
"""Mark a draft PR as ready for review."""
|
|
121
|
+
subprocess.run(
|
|
122
|
+
[
|
|
123
|
+
"gh",
|
|
124
|
+
"pr",
|
|
125
|
+
"ready",
|
|
126
|
+
pr_url,
|
|
127
|
+
"--repo",
|
|
128
|
+
self.repo,
|
|
129
|
+
],
|
|
130
|
+
capture_output=True,
|
|
131
|
+
text=True,
|
|
132
|
+
check=True,
|
|
133
|
+
)
|
|
134
|
+
logger.info("Marked PR %s as ready for review", pr_url)
|
|
135
|
+
|
|
136
|
+
def merge(self, pr_url: str, task_id: str, spec_ref: str) -> bool:
|
|
137
|
+
"""Squash-merge a PR, preserving trailers. Returns True on success.
|
|
138
|
+
|
|
139
|
+
If merge conflict, returns False (caller handles NEEDS_REBASE).
|
|
140
|
+
"""
|
|
141
|
+
delete_flag = "--delete-branch" if self.delete_branch else ""
|
|
142
|
+
body = f"Spec-Ref: {spec_ref}\nTask-Ref: {task_id}"
|
|
143
|
+
|
|
144
|
+
cmd = [
|
|
145
|
+
"gh",
|
|
146
|
+
"pr",
|
|
147
|
+
"merge",
|
|
148
|
+
pr_url,
|
|
149
|
+
f"--{self.merge_strategy}",
|
|
150
|
+
"--body",
|
|
151
|
+
body,
|
|
152
|
+
"--repo",
|
|
153
|
+
self.repo,
|
|
154
|
+
]
|
|
155
|
+
if delete_flag:
|
|
156
|
+
cmd.append(delete_flag)
|
|
157
|
+
|
|
158
|
+
result = subprocess.run(
|
|
159
|
+
cmd,
|
|
160
|
+
capture_output=True,
|
|
161
|
+
text=True,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
if result.returncode != 0:
|
|
165
|
+
logger.warning("Merge failed for PR %s: %s", pr_url, result.stderr.strip())
|
|
166
|
+
return False
|
|
167
|
+
|
|
168
|
+
logger.info("Merged PR %s for task %s", pr_url, task_id)
|
|
169
|
+
return True
|
|
170
|
+
|
|
171
|
+
def rebase_branch(self, branch: str, base_branch: str) -> bool:
|
|
172
|
+
"""Rebase a branch onto base. Returns True if clean, False if conflicts."""
|
|
173
|
+
# Checkout the branch
|
|
174
|
+
checkout = subprocess.run(
|
|
175
|
+
["git", "checkout", branch],
|
|
176
|
+
capture_output=True,
|
|
177
|
+
text=True,
|
|
178
|
+
)
|
|
179
|
+
if checkout.returncode != 0:
|
|
180
|
+
logger.warning("Failed to checkout branch %s: %s", branch, checkout.stderr.strip())
|
|
181
|
+
return False
|
|
182
|
+
|
|
183
|
+
# Attempt rebase
|
|
184
|
+
rebase = subprocess.run(
|
|
185
|
+
["git", "rebase", base_branch],
|
|
186
|
+
capture_output=True,
|
|
187
|
+
text=True,
|
|
188
|
+
)
|
|
189
|
+
if rebase.returncode != 0:
|
|
190
|
+
# Abort the rebase on conflict
|
|
191
|
+
subprocess.run(
|
|
192
|
+
["git", "rebase", "--abort"],
|
|
193
|
+
capture_output=True,
|
|
194
|
+
text=True,
|
|
195
|
+
)
|
|
196
|
+
logger.warning("Rebase conflict on branch %s onto %s", branch, base_branch)
|
|
197
|
+
return False
|
|
198
|
+
|
|
199
|
+
logger.info("Rebased branch %s onto %s", branch, base_branch)
|
|
200
|
+
return True
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _spec_name_from_ref(spec_ref: str) -> str:
|
|
204
|
+
"""Derive a spec label name from a spec_ref path.
|
|
205
|
+
|
|
206
|
+
'specs/persistence.md' -> 'persistence'
|
|
207
|
+
'specs/sub/feature.md' -> 'sub/feature'
|
|
208
|
+
"""
|
|
209
|
+
name = spec_ref
|
|
210
|
+
name = re.sub(r"^specs/", "", name)
|
|
211
|
+
name = re.sub(r"\.md$", "", name)
|
|
212
|
+
return name
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hyperloop
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Orchestrator that walks tasks through composable process pipelines using AI agents
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
7
|
+
Requires-Dist: rich>=15.0.0
|
|
8
|
+
Requires-Dist: typer>=0.24.1
|
|
9
|
+
Provides-Extra: dev
|
|
10
|
+
Requires-Dist: pre-commit>=4.0; extra == 'dev'
|
|
11
|
+
Requires-Dist: pyright>=1.1; extra == 'dev'
|
|
12
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
13
|
+
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# hyperloop
|
|
17
|
+
|
|
18
|
+
Walks tasks through composable process pipelines using AI agents. You write specs, it creates tasks, implements them, verifies the work, and merges PRs.
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
- Python 3.12+
|
|
23
|
+
- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) (`claude` on PATH)
|
|
24
|
+
- `gh` CLI (authenticated, for PR management)
|
|
25
|
+
- `git`
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
From PyPI (once published):
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install hyperloop
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
From source (for development or testing):
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
git clone git@github.com:jsell-rh/hyperloop.git
|
|
39
|
+
cd hyperloop
|
|
40
|
+
uv sync --all-extras
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quickstart
|
|
44
|
+
|
|
45
|
+
1. Create a repo with a spec:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
mkdir -p my-project/specs
|
|
49
|
+
cd my-project
|
|
50
|
+
git init && git commit --allow-empty -m "init"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
2. Write a spec. This is what you want built. Be specific about acceptance criteria:
|
|
54
|
+
|
|
55
|
+
```markdown
|
|
56
|
+
<!-- specs/auth.md -->
|
|
57
|
+
# User Authentication
|
|
58
|
+
|
|
59
|
+
Implement JWT-based authentication for the API.
|
|
60
|
+
|
|
61
|
+
## Acceptance Criteria
|
|
62
|
+
|
|
63
|
+
- POST /auth/login accepts email + password, returns JWT
|
|
64
|
+
- POST /auth/register creates a new user account
|
|
65
|
+
- GET /auth/me returns the current user (requires valid JWT)
|
|
66
|
+
- Passwords are hashed with bcrypt, never stored in plaintext
|
|
67
|
+
- JWTs expire after 24 hours
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
3. Run:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# From source:
|
|
74
|
+
uv run hyperloop run --repo owner/repo --branch main
|
|
75
|
+
|
|
76
|
+
# Or if installed:
|
|
77
|
+
hyperloop run --repo owner/repo --branch main
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
4. See what it would do without executing:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
hyperloop run --repo owner/repo --dry-run
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The orchestrator reads your specs, has the PM create tasks in `specs/tasks/`, then walks each task through the default pipeline: implement, verify, merge.
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
Create `.hyperloop.yaml` in your repo root:
|
|
91
|
+
|
|
92
|
+
```yaml
|
|
93
|
+
target:
|
|
94
|
+
base_branch: main
|
|
95
|
+
|
|
96
|
+
runtime:
|
|
97
|
+
max_workers: 4
|
|
98
|
+
|
|
99
|
+
merge:
|
|
100
|
+
auto_merge: true
|
|
101
|
+
strategy: squash
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then just run from the repo directory:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
hyperloop run
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The repo is inferred from your git remote. All settings have sensible defaults.
|
|
111
|
+
|
|
112
|
+
## Customizing Agent Behavior
|
|
113
|
+
|
|
114
|
+
Hyperloop ships with base agent definitions (implementer, verifier, etc.) that work out of the box. To customize them for your project, overlay with patches.
|
|
115
|
+
|
|
116
|
+
### In-repo overlay
|
|
117
|
+
|
|
118
|
+
For single-repo projects. Agent patches live in the repo itself:
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
# .hyperloop.yaml
|
|
122
|
+
overlay: .hyperloop/agents/
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
your-repo/
|
|
127
|
+
├── .hyperloop.yaml
|
|
128
|
+
├── .hyperloop/
|
|
129
|
+
│ └── agents/
|
|
130
|
+
│ ├── implementer-patch.yaml
|
|
131
|
+
│ └── process-patch.yaml
|
|
132
|
+
└── specs/
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
An implementer patch injects your project's persona:
|
|
136
|
+
|
|
137
|
+
```yaml
|
|
138
|
+
# .hyperloop/agents/implementer-patch.yaml
|
|
139
|
+
kind: Agent
|
|
140
|
+
name: implementer
|
|
141
|
+
annotations:
|
|
142
|
+
ambient.io/persona: |
|
|
143
|
+
You work on a Go API service.
|
|
144
|
+
Build: make build. Test: make test. Lint: make lint.
|
|
145
|
+
Follow Clean Architecture. Use dependency injection.
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Shared overlay via gitops repo
|
|
149
|
+
|
|
150
|
+
For teams with multiple repos sharing agent definitions. The overlay lives in a central gitops repo and references the hyperloop base as a kustomize remote resource:
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
# .hyperloop.yaml
|
|
154
|
+
overlay: git@github.com:your-org/agent-gitops//overlays/api
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
# your-org/agent-gitops/overlays/api/kustomization.yaml
|
|
159
|
+
resources:
|
|
160
|
+
- github.com/org/hyperloop//base?ref=v1.0.0
|
|
161
|
+
|
|
162
|
+
patches:
|
|
163
|
+
- path: implementer-patch.yaml
|
|
164
|
+
target:
|
|
165
|
+
kind: Agent
|
|
166
|
+
name: implementer
|
|
167
|
+
- path: process-patch.yaml
|
|
168
|
+
target:
|
|
169
|
+
kind: Process
|
|
170
|
+
name: default
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
This pins the base version and lets you upgrade across all repos by bumping the ref.
|
|
174
|
+
|
|
175
|
+
## Custom Processes
|
|
176
|
+
|
|
177
|
+
The default pipeline is: implement, verify, merge. Override it by patching the process:
|
|
178
|
+
|
|
179
|
+
```yaml
|
|
180
|
+
# process-patch.yaml
|
|
181
|
+
kind: Process
|
|
182
|
+
name: default
|
|
183
|
+
|
|
184
|
+
pipeline:
|
|
185
|
+
- loop:
|
|
186
|
+
- loop:
|
|
187
|
+
- role: implementer
|
|
188
|
+
- role: verifier
|
|
189
|
+
- role: security-reviewer
|
|
190
|
+
- gate: human-pr-approval
|
|
191
|
+
- action: merge-pr
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Four primitives:
|
|
195
|
+
|
|
196
|
+
| Primitive | What it does |
|
|
197
|
+
|---|---|
|
|
198
|
+
| `role: X` | Spawn an agent. Fail restarts the enclosing loop. |
|
|
199
|
+
| `gate: X` | Block until external signal (v1: `lgtm` label on PR). |
|
|
200
|
+
| `loop` | Wrap steps. Retry from top on failure. |
|
|
201
|
+
| `action: X` | Terminal operation (`merge-pr`, `mark-pr-ready`). |
|
|
202
|
+
|
|
203
|
+
Loops nest. Inner loops retry independently of outer loops.
|
|
204
|
+
|
|
205
|
+
## What it creates in your repo
|
|
206
|
+
|
|
207
|
+
The orchestrator writes to `specs/` in your repo:
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
specs/
|
|
211
|
+
├── tasks/ # task files with status, findings, spec references
|
|
212
|
+
├── reviews/ # review artifacts from verifier (on branches)
|
|
213
|
+
└── prompts/ # process improvements (learned over time)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
All task state is tracked in git. Every commit includes `Spec-Ref` and `Task-Ref` trailers for traceability. PRs are created as drafts and labeled by spec and task.
|
|
217
|
+
|
|
218
|
+
## Configuration Reference
|
|
219
|
+
|
|
220
|
+
```yaml
|
|
221
|
+
# .hyperloop.yaml
|
|
222
|
+
|
|
223
|
+
overlay: .hyperloop/agents/ # local path or git URL to kustomization dir
|
|
224
|
+
|
|
225
|
+
target:
|
|
226
|
+
repo: owner/repo # GitHub repo (default: inferred from git remote)
|
|
227
|
+
base_branch: main # trunk branch
|
|
228
|
+
specs_dir: specs # where specs live
|
|
229
|
+
|
|
230
|
+
runtime:
|
|
231
|
+
default: local # local (v1) | ambient (planned)
|
|
232
|
+
max_workers: 6 # max parallel task workers
|
|
233
|
+
|
|
234
|
+
merge:
|
|
235
|
+
auto_merge: true # squash-merge on review pass
|
|
236
|
+
strategy: squash # squash | merge
|
|
237
|
+
delete_branch: true # delete worker branch after merge
|
|
238
|
+
|
|
239
|
+
poll_interval: 30 # seconds between orchestrator cycles
|
|
240
|
+
max_rounds: 50 # max retry rounds per task before failure
|
|
241
|
+
max_rebase_attempts: 3 # max rebase retries before full loop retry
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Development
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
uv sync --all-extras
|
|
248
|
+
uv run pytest # run tests (280 tests)
|
|
249
|
+
uv run ruff check . # lint
|
|
250
|
+
uv run ruff format --check . # format check
|
|
251
|
+
uv run pyright # type check
|
|
252
|
+
uv run hyperloop --help # CLI help
|
|
253
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
hyperloop/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
hyperloop/__main__.py,sha256=BSNHOzDGZgtLbVpUCzfZF85qaTEnASWqVun0CejFvaA,85
|
|
3
|
+
hyperloop/cli.py,sha256=GXBxZFJb8q3kkh0oR_7yCtmcrmiII0wcedwWDrCDvrs,5076
|
|
4
|
+
hyperloop/compose.py,sha256=rK1uWMzLVPlOwfqmmpJsZddFeAsw6eCiqWpPZlIdg0Q,4482
|
|
5
|
+
hyperloop/config.py,sha256=s9v1CbGvfby2C9Hd_rtVDYj3LfmHtfJUnFMGue0KNeE,5303
|
|
6
|
+
hyperloop/loop.py,sha256=bH8J1SbVbfSDe_4RPSRmXyYcciazdB_z4G5yvMXhmZ8,19937
|
|
7
|
+
hyperloop/pr.py,sha256=2Q5cnpnLLOdn41ba_zkmCuFdJEhuUABYPX6yGlWJQIM,6071
|
|
8
|
+
hyperloop/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
hyperloop/adapters/git_state.py,sha256=8Da6lSMLwf3qP1Rn9WakAJ-88YQc8no36aoZbrfLCpQ,9003
|
|
10
|
+
hyperloop/adapters/local.py,sha256=I-YCR76pa_bY5seac-29QRJWSI5DKhL0psNgrcIQfps,9262
|
|
11
|
+
hyperloop/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
hyperloop/domain/decide.py,sha256=c9RbT1zYw3_neeswM1-fQPvIC_mEbQ98SvlaAXekShs,3996
|
|
13
|
+
hyperloop/domain/deps.py,sha256=wMgGWpxxqmGdrobtVCRf32GMTs5DBaGIY0Yzx9rz9bg,2039
|
|
14
|
+
hyperloop/domain/model.py,sha256=4QBJY-U2CCIUfNoIl6zhoDQfKzZg21yyVuXyE0O4cik,4926
|
|
15
|
+
hyperloop/domain/pipeline.py,sha256=sIR9_gaNf-XHoYkrJYkuTO5sZ92UMmfvTJH8CSCzq0M,10712
|
|
16
|
+
hyperloop/ports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
hyperloop/ports/pr.py,sha256=giSAGDk-vl4ycMJUdewSRk2ASu80_r_t9wJFxo1gGMA,1066
|
|
18
|
+
hyperloop/ports/runtime.py,sha256=KeZ4BZozRpv_5MrqEjlYd47AgEzyQ81f79GaTIEDzk0,1229
|
|
19
|
+
hyperloop/ports/state.py,sha256=WT_JSaYo8t5nlgqwd64I5JB214iRm0pI25wU7jaw4OE,1814
|
|
20
|
+
hyperloop-0.1.0.dist-info/METADATA,sha256=XlcOvCQZEKm_GOWw2HIX5QS0-vkbRorVxKSHFQZ10jc,6327
|
|
21
|
+
hyperloop-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
22
|
+
hyperloop-0.1.0.dist-info/entry_points.txt,sha256=bP63nmW_9q_pSa8GOaP1svkdkVfX_MWd-QuKSYsPis8,48
|
|
23
|
+
hyperloop-0.1.0.dist-info/RECORD,,
|