@ccoalm/ccl-skills 0.15.1 → 0.15.2
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.
- package/README.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/agent-context/session-start.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/SKILL.md +2 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/SKILL.md +6 -5
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/development-completion.md +26 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/staged-review-contract.md +37 -13
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/AGENTS.md +5 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/codex_review.sh +77 -5
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/kimi_packet_mcp.py +98 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_cli_review.py +48 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/review_gate.py +230 -16
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_cli_review_wrappers.sh +165 -11
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_kimi_packet_mcp.py +143 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_client_compat.py +572 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/SKILL.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/SKILL.md +2 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-agent-delegation/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/nodejs-service-dev/SKILL.md +2 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/SKILL.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/SKILL.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/SKILL.md +2 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/SKILL.md +7 -7
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/design-review-gate-mechanics.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/pre-final-continuation-gate.md +20 -11
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/refactoring-discipline.md +7 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md +2 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/dual-track-review-gate.md +17 -17
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/harness-patterns-and-eval.md +4 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/resume-paused-delivery.md +3 -3
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +11 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_ai_coding_implementation_gates.sh +83 -48
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_body_compliance_grading.sh +80 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_controlled_escalation_pins.sh +3 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_extraction_review_state.sh +190 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/validate_extraction_review_state.py +106 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/terminal-cli-dev/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/SKILL.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/SKILL.md +1 -1
- package/dist/assets/release.json +54 -49
- package/dist/codex-host.d.ts +1 -1
- package/dist/codex-host.js +39 -15
- package/dist/host-probe.d.ts +16 -0
- package/dist/host-probe.js +29 -5
- package/dist/operations.js +34 -8
- package/dist/unified.d.ts +1 -1
- package/dist/unified.js +11 -4
- package/package.json +1 -1
|
@@ -78,6 +78,149 @@ class PacketMcpTest(unittest.TestCase):
|
|
|
78
78
|
[{"type": "text", "text": "PACKET_CHUNK 6:17/17\nbeta\ngamma\n"}],
|
|
79
79
|
)
|
|
80
80
|
|
|
81
|
+
response = self.request(
|
|
82
|
+
4,
|
|
83
|
+
"tools/call",
|
|
84
|
+
{
|
|
85
|
+
"name": "search_packet",
|
|
86
|
+
"arguments": {"query": "alpha", "byte_offset": 0, "limit": 1},
|
|
87
|
+
},
|
|
88
|
+
)
|
|
89
|
+
self.assertTrue(response["result"]["isError"])
|
|
90
|
+
self.assertEqual(response["result"]["content"][0]["text"], "unknown tool")
|
|
91
|
+
|
|
92
|
+
def search_exchange(self, text: str, arguments: list[object]) -> list[dict]:
|
|
93
|
+
packet = Path(self.temp.name) / "search.txt"
|
|
94
|
+
packet.write_text(text, encoding="utf-8")
|
|
95
|
+
digest = hashlib.sha256(packet.read_bytes()).hexdigest()
|
|
96
|
+
requests = [{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}]
|
|
97
|
+
requests.extend(
|
|
98
|
+
{
|
|
99
|
+
"jsonrpc": "2.0",
|
|
100
|
+
"id": index,
|
|
101
|
+
"method": "tools/call",
|
|
102
|
+
"params": {"name": "search_packet", "arguments": item},
|
|
103
|
+
}
|
|
104
|
+
for index, item in enumerate(arguments, 2)
|
|
105
|
+
)
|
|
106
|
+
completed = subprocess.run(
|
|
107
|
+
[sys.executable, str(SERVER), "--packet", str(packet), "--sha256", digest,
|
|
108
|
+
"--allow-search"],
|
|
109
|
+
input="\n".join(json.dumps(item) for item in requests) + "\n",
|
|
110
|
+
capture_output=True,
|
|
111
|
+
text=True,
|
|
112
|
+
timeout=5,
|
|
113
|
+
check=False,
|
|
114
|
+
)
|
|
115
|
+
self.assertEqual(completed.returncode, 0, completed.stderr)
|
|
116
|
+
return [json.loads(line)["result"] for line in completed.stdout.splitlines()]
|
|
117
|
+
|
|
118
|
+
def test_search_opt_in_tool_surface(self) -> None:
|
|
119
|
+
response = self.search_exchange("alpha", [])[0]
|
|
120
|
+
self.assertEqual(
|
|
121
|
+
[tool["name"] for tool in response["tools"]],
|
|
122
|
+
["read_packet", "search_packet"],
|
|
123
|
+
)
|
|
124
|
+
schema = response["tools"][1]["inputSchema"]
|
|
125
|
+
self.assertEqual(schema["required"], ["query", "byte_offset", "limit"])
|
|
126
|
+
self.assertEqual(set(schema["properties"]), {"query", "byte_offset", "limit"})
|
|
127
|
+
self.assertFalse(schema["additionalProperties"])
|
|
128
|
+
|
|
129
|
+
def test_search_literal_utf8_matches_use_byte_offsets_and_bounded_pagination(self) -> None:
|
|
130
|
+
responses = self.search_exchange("é alpha\n你.* 你.*\nalpha\n", [
|
|
131
|
+
{"query": "你.*", "byte_offset": 0, "limit": 1},
|
|
132
|
+
{"query": "你.*", "byte_offset": 14, "limit": 1},
|
|
133
|
+
{"query": ".*", "byte_offset": 0, "limit": 100},
|
|
134
|
+
{"query": "missing", "byte_offset": 0, "limit": 1},
|
|
135
|
+
{"query": "alpha", "byte_offset": 27, "limit": 1},
|
|
136
|
+
])
|
|
137
|
+
expected = [
|
|
138
|
+
{"matches": [{"byte_offset": 9, "line": 2}], "next_byte_offset": 14, "total_bytes": 27},
|
|
139
|
+
{"matches": [{"byte_offset": 15, "line": 2}], "next_byte_offset": None, "total_bytes": 27},
|
|
140
|
+
{"matches": [{"byte_offset": 12, "line": 2}, {"byte_offset": 18, "line": 2}], "next_byte_offset": None, "total_bytes": 27},
|
|
141
|
+
{"matches": [], "next_byte_offset": None, "total_bytes": 27},
|
|
142
|
+
{"matches": [], "next_byte_offset": None, "total_bytes": 27},
|
|
143
|
+
]
|
|
144
|
+
for response, result in zip(responses[1:], expected, strict=True):
|
|
145
|
+
self.assertFalse(response["isError"])
|
|
146
|
+
self.assertEqual(json.loads(response["content"][0]["text"]), result)
|
|
147
|
+
|
|
148
|
+
def test_search_rejects_invalid_arguments_and_offsets(self) -> None:
|
|
149
|
+
valid = {"query": "a", "byte_offset": 0, "limit": 1}
|
|
150
|
+
invalid = [None, [], {}, {**valid, "path": "/etc/passwd"},
|
|
151
|
+
{**valid, "query": ""}, {**valid, "query": 1},
|
|
152
|
+
{**valid, "query": "你" * 341 + "xy"}, {**valid, "query": "\ud800"},
|
|
153
|
+
{**valid, "byte_offset": -1}, {**valid, "byte_offset": True},
|
|
154
|
+
{**valid, "byte_offset": False},
|
|
155
|
+
{**valid, "byte_offset": 1.5}, {**valid, "limit": 0},
|
|
156
|
+
{**valid, "limit": 101}, {**valid, "limit": True},
|
|
157
|
+
{**valid, "limit": 1.5}, {**valid, "byte_offset": 1},
|
|
158
|
+
{**valid, "byte_offset": 4}]
|
|
159
|
+
responses = self.search_exchange("你", invalid)
|
|
160
|
+
self.assertEqual(len(responses), len(invalid) + 1)
|
|
161
|
+
for arguments, response in zip(invalid, responses[1:], strict=True):
|
|
162
|
+
with self.subTest(arguments=arguments):
|
|
163
|
+
self.assertTrue(response["isError"])
|
|
164
|
+
|
|
165
|
+
def test_search_is_case_sensitive_and_non_overlapping(self) -> None:
|
|
166
|
+
responses = self.search_exchange("AaAAaaaa\n", [
|
|
167
|
+
{"query": "aa", "byte_offset": 0, "limit": 100},
|
|
168
|
+
{"query": "AA", "byte_offset": 0, "limit": 100},
|
|
169
|
+
])
|
|
170
|
+
expected = [[{"byte_offset": 4, "line": 1}, {"byte_offset": 6, "line": 1}],
|
|
171
|
+
[{"byte_offset": 2, "line": 1}]]
|
|
172
|
+
for response, matches in zip(responses[1:], expected, strict=True):
|
|
173
|
+
self.assertFalse(response["isError"])
|
|
174
|
+
self.assertEqual(json.loads(response["content"][0]["text"]), {
|
|
175
|
+
"matches": matches, "next_byte_offset": None, "total_bytes": 9,
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
def test_search_accepts_the_maximum_query_byte_length(self) -> None:
|
|
179
|
+
query = "你" * 341 + "x"
|
|
180
|
+
response = self.search_exchange(query, [
|
|
181
|
+
{"query": query, "byte_offset": 0, "limit": 1},
|
|
182
|
+
])[1]
|
|
183
|
+
self.assertFalse(response["isError"])
|
|
184
|
+
self.assertEqual(json.loads(response["content"][0]["text"]), {
|
|
185
|
+
"matches": [{"byte_offset": 0, "line": 1}],
|
|
186
|
+
"next_byte_offset": None,
|
|
187
|
+
"total_bytes": 1024,
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
def test_search_limits_results_without_returning_an_oversized_line(self) -> None:
|
|
191
|
+
responses = self.search_exchange("x" * 48_001 + "\n", [
|
|
192
|
+
{"query": "x", "byte_offset": 0, "limit": 100},
|
|
193
|
+
{"query": "x", "byte_offset": 100, "limit": 1},
|
|
194
|
+
])
|
|
195
|
+
first = json.loads(responses[1]["content"][0]["text"])
|
|
196
|
+
self.assertEqual(first, {
|
|
197
|
+
"matches": [{"byte_offset": offset, "line": 1} for offset in range(100)],
|
|
198
|
+
"next_byte_offset": 100,
|
|
199
|
+
"total_bytes": 48_002,
|
|
200
|
+
})
|
|
201
|
+
second = json.loads(responses[2]["content"][0]["text"])
|
|
202
|
+
self.assertEqual(second["matches"], [{"byte_offset": 100, "line": 1}])
|
|
203
|
+
for response in responses[1:]:
|
|
204
|
+
self.assertFalse(response["isError"])
|
|
205
|
+
self.assertLessEqual(len(response["content"][0]["text"].encode("utf-8")), 48_000)
|
|
206
|
+
|
|
207
|
+
def test_search_rechecks_exact_packet_binding_after_each_call(self) -> None:
|
|
208
|
+
self.process.terminate()
|
|
209
|
+
self.process.communicate(timeout=5)
|
|
210
|
+
digest = hashlib.sha256(self.packet.read_bytes()).hexdigest()
|
|
211
|
+
self.process = subprocess.Popen(
|
|
212
|
+
[sys.executable, str(SERVER), "--packet", str(self.packet), "--sha256", digest,
|
|
213
|
+
"--allow-search"],
|
|
214
|
+
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True,
|
|
215
|
+
)
|
|
216
|
+
self.initialize()
|
|
217
|
+
params = {"name": "search_packet", "arguments": {"query": "alpha", "byte_offset": 0, "limit": 1}}
|
|
218
|
+
self.assertFalse(self.request(2, "tools/call", params)["result"]["isError"])
|
|
219
|
+
self.packet.write_text("ALPHA\nbeta\ngamma\n", encoding="utf-8")
|
|
220
|
+
response = self.request(3, "tools/call", params)["result"]
|
|
221
|
+
self.assertTrue(response["isError"])
|
|
222
|
+
self.assertEqual(response["content"][0]["text"], "packet binding changed")
|
|
223
|
+
|
|
81
224
|
def test_rejects_path_arguments_and_packet_mutation(self) -> None:
|
|
82
225
|
self.initialize()
|
|
83
226
|
response = self.request(
|