pactkit-opencode 4.0.0__tar.gz → 4.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/PKG-INFO +2 -2
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/pyproject.toml +2 -2
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode/deployer.py +25 -10
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode.egg-info/PKG-INFO +2 -2
- pactkit_opencode-4.1.0/src/pactkit_opencode.egg-info/requires.txt +1 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_step8_declaration_search_producer.py +16 -4
- pactkit_opencode-4.0.0/src/pactkit_opencode.egg-info/requires.txt +0 -1
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/README.md +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/setup.cfg +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode/__init__.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode/declarations.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode/enforcement.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode.egg-info/SOURCES.txt +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode.egg-info/dependency_links.txt +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode.egg-info/entry_points.txt +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode.egg-info/top_level.txt +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_a1_config_recovery.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_a2_mcp_retired.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_bug035_opencode_dual_layer.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_capability_contract.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_deploy_opencode_parity.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_gate_plugin_deploy.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_host_body_snapshot.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_opencode_enforcement_channel.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_profile_contract.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_step6_self_sufficiency.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_story069_opencode_format.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_story070_opencode_compliance.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_story071_opencode_config_parity.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_story073_command_model_routing.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_story_work_units.py +0 -0
- {pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_wire_format_contract.py +0 -0
|
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pactkit-opencode"
|
|
7
|
-
version = "4.
|
|
7
|
+
version = "4.1.0"
|
|
8
8
|
description = "PactKit adapter for OpenCode IDE"
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
license = "MIT"
|
|
11
11
|
dependencies = [
|
|
12
|
-
"pactkit>=4.
|
|
12
|
+
"pactkit>=4.1.0,<4.2.0",
|
|
13
13
|
]
|
|
14
14
|
|
|
15
15
|
[project.entry-points."pactkit.deployers"]
|
|
@@ -133,8 +133,22 @@ class OpenCodeDeployer(DeployerBase):
|
|
|
133
133
|
deployment_claim = declarations.DEPLOYMENT_CLAIM
|
|
134
134
|
input_translation = declarations.INPUT_TRANSLATION
|
|
135
135
|
|
|
136
|
-
def deploy(self, config=None, target=None):
|
|
136
|
+
def deploy(self, config=None, target=None, project_root=None, no_redetect=False):
|
|
137
|
+
"""Deploy PactKit configuration for OpenCode.
|
|
138
|
+
|
|
139
|
+
``project_root`` is **not** the deploy root: OpenCode installs globally
|
|
140
|
+
under ``~/.config/opencode``, and the two MUST NOT be confused. It
|
|
141
|
+
names the project whose config, overlay and CI file are read/written —
|
|
142
|
+
those used to resolve from the caller's cwd, so ``pactkit -C
|
|
143
|
+
<other-project>`` read the wrong project's policy.
|
|
144
|
+
|
|
145
|
+
``no_redetect`` is accepted because the Core dispatcher passes it
|
|
146
|
+
alongside ``project_root``; it is a no-op here — this deployer's
|
|
147
|
+
stack probe only reads the filesystem and never writes the stack
|
|
148
|
+
back into the config.
|
|
149
|
+
"""
|
|
137
150
|
opencode_root = Path(target) if target else Path.home() / ".config" / "opencode"
|
|
151
|
+
project_root = Path(project_root) if project_root is not None else Path.cwd()
|
|
138
152
|
|
|
139
153
|
print("🚀 PactKit OpenCode Deployment")
|
|
140
154
|
|
|
@@ -150,7 +164,7 @@ class OpenCodeDeployer(DeployerBase):
|
|
|
150
164
|
# STORY-slim-008 R1+R2: Load config from project-level pactkit.yaml
|
|
151
165
|
from pactkit.config import find_pactkit_yaml
|
|
152
166
|
|
|
153
|
-
project_yaml = find_pactkit_yaml()
|
|
167
|
+
project_yaml = find_pactkit_yaml(project_root)
|
|
154
168
|
|
|
155
169
|
if config is not None:
|
|
156
170
|
cfg = config
|
|
@@ -161,7 +175,7 @@ class OpenCodeDeployer(DeployerBase):
|
|
|
161
175
|
cfg = load_config(project_yaml)
|
|
162
176
|
else:
|
|
163
177
|
cfg = {}
|
|
164
|
-
cfg = activate_pactkit_maintainer_overlay(cfg,
|
|
178
|
+
cfg = activate_pactkit_maintainer_overlay(cfg, project_root)
|
|
165
179
|
|
|
166
180
|
enabled_agents = cfg.get("agents", sorted(VALID_AGENTS))
|
|
167
181
|
enabled_skills = cfg.get("skills", sorted(VALID_SKILLS))
|
|
@@ -239,7 +253,6 @@ class OpenCodeDeployer(DeployerBase):
|
|
|
239
253
|
|
|
240
254
|
ci_config = cfg.get("ci", {})
|
|
241
255
|
ci_provider = ci_config.get("provider", "none") if isinstance(ci_config, dict) else "none"
|
|
242
|
-
project_root = Path.cwd()
|
|
243
256
|
_deploy_ci(ci_provider, project_root, cfg)
|
|
244
257
|
|
|
245
258
|
# STORY-slim-139 R2: machine-readable deployment manifest
|
|
@@ -264,8 +277,8 @@ class OpenCodeDeployer(DeployerBase):
|
|
|
264
277
|
)
|
|
265
278
|
|
|
266
279
|
if target is None:
|
|
267
|
-
self._generate_project_agents_md()
|
|
268
|
-
self._generate_project_config()
|
|
280
|
+
self._generate_project_agents_md(project_root)
|
|
281
|
+
self._generate_project_config(project_root)
|
|
269
282
|
|
|
270
283
|
# --- OpenCode-specific helpers ---
|
|
271
284
|
|
|
@@ -291,7 +304,7 @@ class OpenCodeDeployer(DeployerBase):
|
|
|
291
304
|
return 1
|
|
292
305
|
|
|
293
306
|
@staticmethod
|
|
294
|
-
def _generate_project_config():
|
|
307
|
+
def _generate_project_config(project_root=None):
|
|
295
308
|
"""Write this host's pactkit.yaml when the project has none (Step 8 R-③-1).
|
|
296
309
|
|
|
297
310
|
Before this existed, `.opencode/pactkit.yaml` was **declared** in
|
|
@@ -306,15 +319,17 @@ class OpenCodeDeployer(DeployerBase):
|
|
|
306
319
|
`format="opencode"` closes both halves: this host produces its own
|
|
307
320
|
copy, and no other host can produce this one's.
|
|
308
321
|
"""
|
|
309
|
-
|
|
322
|
+
# Direct callers may omit the root; the deploy path always passes it.
|
|
323
|
+
project_root = Path(project_root) if project_root is not None else Path.cwd()
|
|
310
324
|
if project_root.resolve() == Path.home().resolve():
|
|
311
325
|
return
|
|
312
326
|
generate_config_if_missing(format="opencode", project_root=project_root)
|
|
313
327
|
|
|
314
328
|
@staticmethod
|
|
315
|
-
def _generate_project_agents_md():
|
|
329
|
+
def _generate_project_agents_md(project_root=None):
|
|
316
330
|
"""Generate project-level AGENTS.md if it does not exist (STORY-slim-008 R4)."""
|
|
317
|
-
|
|
331
|
+
# Direct callers may omit the root; the deploy path always passes it.
|
|
332
|
+
project_root = Path(project_root) if project_root is not None else Path.cwd()
|
|
318
333
|
if project_root.resolve() == Path.home().resolve():
|
|
319
334
|
return
|
|
320
335
|
agents_md_path = project_root / "AGENTS.md"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pactkit<4.2.0,>=4.1.0
|
{pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_step8_declaration_search_producer.py
RENAMED
|
@@ -130,17 +130,24 @@ class TestTheThreeFactsAgree:
|
|
|
130
130
|
"""内容来自 core 的 canonical generator,不是本仓的第二份模板。
|
|
131
131
|
|
|
132
132
|
逐字段断言会在「core 改了格式而本仓漂移」时照样通过;比字节不会。
|
|
133
|
+
|
|
134
|
+
**两层各比各的生成器**(STORY-slim-20260928c7b15e04a216 Step 1a):
|
|
135
|
+
共享根对 `generate_default_yaml`,宿主路径对 `generate_sparse_host_yaml`。
|
|
136
|
+
只比其中一层,另一层就能悄悄漂移。
|
|
133
137
|
"""
|
|
134
138
|
from pactkit.cleaners import detect_stacks
|
|
135
|
-
from pactkit.config import generate_default_yaml
|
|
139
|
+
from pactkit.config import generate_default_yaml, generate_sparse_host_yaml
|
|
136
140
|
from pactkit.profiles import get_profile
|
|
137
141
|
|
|
138
142
|
from pactkit_opencode import OpenCodeDeployer
|
|
139
143
|
|
|
140
144
|
OpenCodeDeployer().deploy()
|
|
141
145
|
|
|
142
|
-
|
|
143
|
-
assert
|
|
146
|
+
shared = (project / "pactkit.yaml").read_text()
|
|
147
|
+
assert shared == generate_default_yaml(stack=detect_stacks(project))
|
|
148
|
+
|
|
149
|
+
host = (project / get_profile("opencode").pactkit_yaml_path).read_text()
|
|
150
|
+
assert host == generate_sparse_host_yaml()
|
|
144
151
|
|
|
145
152
|
def test_the_config_is_valid_and_carries_the_format_version(self, project):
|
|
146
153
|
from pactkit.config import VALID_STACKS
|
|
@@ -154,7 +161,12 @@ class TestTheThreeFactsAgree:
|
|
|
154
161
|
(project / get_profile("opencode").pactkit_yaml_path).read_text()
|
|
155
162
|
)
|
|
156
163
|
assert data["schema_version"] == 1
|
|
157
|
-
|
|
164
|
+
# 策略在共享根里;宿主层是**覆盖**,不是策略的第二份副本。
|
|
165
|
+
shared = yaml.safe_load((project / "pactkit.yaml").read_text())
|
|
166
|
+
assert shared["stack"] in VALID_STACKS
|
|
167
|
+
assert "stack" not in data, (
|
|
168
|
+
f"宿主层重复了项目策略:{sorted(data)}"
|
|
169
|
+
)
|
|
158
170
|
|
|
159
171
|
|
|
160
172
|
class TestTheCrossWriteIsClosed:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pactkit<4.1.0,>=4.0.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/src/pactkit_opencode.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_opencode_enforcement_channel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_story070_opencode_compliance.py
RENAMED
|
File without changes
|
{pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_story071_opencode_config_parity.py
RENAMED
|
File without changes
|
{pactkit_opencode-4.0.0 → pactkit_opencode-4.1.0}/tests/test_story073_command_model_routing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|